diff --git a/reactos/dll/ntdll/csr/capture.c b/reactos/dll/ntdll/csr/capture.c index 0a779eca9f9..ad266250c9b 100644 --- a/reactos/dll/ntdll/csr/capture.c +++ b/reactos/dll/ntdll/csr/capture.c @@ -3,7 +3,8 @@ * PROJECT: ReactOS kernel * FILE: dll/ntdll/csr/capture.c * PURPOSE: Routines for probing and capturing CSR API Messages - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ @@ -131,7 +132,7 @@ ULONG NTAPI CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN ULONG MessageLength, - OUT PVOID *CapturedData) + OUT PVOID* CapturedData) { if (MessageLength == 0) { @@ -168,7 +169,7 @@ NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, - OUT PVOID *CapturedData) + OUT PVOID* CapturedData) { /* Simply allocate a message pointer in the buffer */ CsrAllocateMessagePointer(CaptureBuffer, MessageLength, CapturedData); @@ -191,35 +192,23 @@ CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer) RtlFreeHeap(CsrPortHeap, 0, CaptureBuffer); } -/* - * @unimplemented - */ -NTSTATUS -NTAPI -CsrCaptureMessageMultiUnicodeStringsInPlace(IN PCSR_CAPTURE_BUFFER *CaptureBuffer, - IN ULONG MessageCount, - IN PVOID MessageStrings) -{ - /* FIXME: allocate a buffer if we don't have one, and return it */ - /* FIXME: call CsrCaptureMessageUnicodeStringInPlace for each string */ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - /* * @implemented */ VOID NTAPI CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, - IN LPSTR String OPTIONAL, + IN PCSTR String OPTIONAL, IN ULONG StringLength, IN ULONG MaximumLength, - OUT PANSI_STRING CapturedString) + OUT PSTRING CapturedString) { - ULONG ReturnedLength; + ASSERT(CapturedString != NULL); - /* If we don't have a string, initialize an empty one */ + /* + * If we don't have a string, initialize an empty one, + * otherwise capture the given string. + */ if (!String) { CapturedString->Length = 0; @@ -229,31 +218,95 @@ CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, CsrAllocateMessagePointer(CaptureBuffer, MaximumLength, (PVOID*)&CapturedString->Buffer); - return; } - - /* Initialize this string */ - CapturedString->Length = (USHORT)StringLength; - - /* Allocate a buffer and get its size */ - ReturnedLength = CsrAllocateMessagePointer(CaptureBuffer, - MaximumLength, - (PVOID*)&CapturedString->Buffer); - CapturedString->MaximumLength = (USHORT)ReturnedLength; - - /* If the string had data */ - if (StringLength) + else { - /* Copy it into the capture buffer */ - RtlMoveMemory(CapturedString->Buffer, String, MaximumLength); + /* Cut-off the string length if needed */ + if (StringLength > MaximumLength) + StringLength = MaximumLength; - /* If we don't take up the whole space */ - if (CapturedString->Length < CapturedString->MaximumLength) - { - /* Null-terminate it */ - CapturedString->Buffer[CapturedString->Length] = '\0'; - } + CapturedString->Length = (USHORT)StringLength; + + /* Allocate a buffer and get its size */ + CapturedString->MaximumLength = + (USHORT)CsrAllocateMessagePointer(CaptureBuffer, + MaximumLength, + (PVOID*)&CapturedString->Buffer); + + /* If the string has data, copy it into the buffer */ + if (StringLength) + RtlMoveMemory(CapturedString->Buffer, String, StringLength); } + + /* Null-terminate the string if we don't take up the whole space */ + if (CapturedString->Length < CapturedString->MaximumLength) + CapturedString->Buffer[CapturedString->Length] = '\0'; +} + +static VOID +CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, + IN PUNICODE_STRING String) +{ + ASSERT(String != NULL); + + /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */ + CsrCaptureMessageString(CaptureBuffer, + (PCSTR)String->Buffer, + String->Length, + String->MaximumLength, + (PSTRING)String); + + /* Null-terminate the string */ + if (String->MaximumLength >= String->Length + sizeof(WCHAR)) + { + String->Buffer[String->Length / sizeof(WCHAR)] = L'\0'; + } +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER* CaptureBuffer, + IN ULONG StringsCount, + IN PUNICODE_STRING* MessageStrings) +{ + ULONG Count; + + if (!CaptureBuffer) return STATUS_INVALID_PARAMETER; + + /* Allocate a new capture buffer if we don't have one already */ + if (!*CaptureBuffer) + { + /* Compute the required size for the capture buffer */ + ULONG Size = 0; + + Count = 0; + while (Count < StringsCount) + { + if (MessageStrings[Count]) + Size += MessageStrings[Count]->MaximumLength; + + ++Count; + } + + /* Allocate the capture buffer */ + *CaptureBuffer = CsrAllocateCaptureBuffer(StringsCount, Size); + if (!*CaptureBuffer) return STATUS_NO_MEMORY; + } + + /* Now capture each UNICODE string */ + Count = 0; + while (Count < StringsCount) + { + if (MessageStrings[Count]) + CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer, MessageStrings[Count]); + + ++Count; + } + + return STATUS_SUCCESS; } /* diff --git a/reactos/dll/win32/kernel32/client/console/alias.c b/reactos/dll/win32/kernel32/client/console/alias.c index 05f05f3e9a5..a949c75cb6b 100644 --- a/reactos/dll/win32/kernel32/client/console/alias.c +++ b/reactos/dll/win32/kernel32/client/console/alias.c @@ -18,31 +18,40 @@ /* FUNCTIONS ******************************************************************/ -/* - * @implemented - */ -BOOL -WINAPI -AddConsoleAliasW(LPCWSTR lpSource, - LPCWSTR lpTarget, - LPCWSTR lpExeName) +static BOOL +IntAddConsoleAlias(LPCVOID Source, + USHORT SourceBufferLength, + LPCVOID Target, + USHORT TargetBufferLength, + LPCVOID lpExeName, + BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &ApiMessage.Data.ConsoleAliasRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; ULONG CapturedStrings; - DPRINT("AddConsoleAliasW enterd with lpSource %S lpTarget %S lpExeName %S\n", lpSource, lpTarget, lpExeName); + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); + + if (lpExeName == NULL || NumChars == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ConsoleAliasRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; /* Determine the needed sizes */ - ConsoleAliasRequest->SourceLength = (wcslen(lpSource ) + 1) * sizeof(WCHAR); - ConsoleAliasRequest->ExeLength = (wcslen(lpExeName) + 1) * sizeof(WCHAR); + ConsoleAliasRequest->SourceLength = SourceBufferLength; + ConsoleAliasRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + ConsoleAliasRequest->Unicode = + ConsoleAliasRequest->Unicode2 = bUnicode; + CapturedStrings = 2; - if (lpTarget) /* The target can be optional */ + if (Target) /* The target can be optional */ { - ConsoleAliasRequest->TargetLength = (wcslen(lpTarget) + 1) * sizeof(WCHAR); + ConsoleAliasRequest->TargetLength = TargetBufferLength; CapturedStrings++; } else @@ -64,19 +73,19 @@ AddConsoleAliasW(LPCWSTR lpSource, /* Capture the strings */ CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpSource, + (PVOID)Source, ConsoleAliasRequest->SourceLength, (PVOID*)&ConsoleAliasRequest->Source); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, ConsoleAliasRequest->ExeLength, - (PVOID*)&ConsoleAliasRequest->Exe); + (PVOID*)&ConsoleAliasRequest->ExeName); - if (lpTarget) /* The target can be optional */ + if (Target) /* The target can be optional */ { CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpTarget, + (PVOID)Target, ConsoleAliasRequest->TargetLength, (PVOID*)&ConsoleAliasRequest->Target); } @@ -85,16 +94,16 @@ AddConsoleAliasW(LPCWSTR lpSource, ConsoleAliasRequest->Target = NULL; } - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAddAlias), - sizeof(CONSOLE_ADDGETALIAS)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAddAlias), + sizeof(*ConsoleAliasRequest)); CsrFreeCaptureBuffer(CaptureBuffer); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return FALSE; } @@ -107,64 +116,83 @@ AddConsoleAliasW(LPCWSTR lpSource, */ BOOL WINAPI -AddConsoleAliasA(LPCSTR lpSource, - LPCSTR lpTarget, - LPCSTR lpExeName) +AddConsoleAliasW(LPCWSTR lpSource, + LPCWSTR lpTarget, + LPCWSTR lpExeName) { - LPWSTR lpSourceW = NULL; - LPWSTR lpTargetW = NULL; - LPWSTR lpExeNameW = NULL; - BOOL bRetVal; + USHORT SourceBufferLength = (USHORT)wcslen(lpSource) * sizeof(WCHAR); + USHORT TargetBufferLength = (USHORT)(lpTarget ? wcslen(lpTarget) * sizeof(WCHAR) : 0); - if (lpSource) - BasepAnsiStringToHeapUnicodeString(lpSource, (LPWSTR*)&lpSourceW); - if (lpTarget) - BasepAnsiStringToHeapUnicodeString(lpTarget, (LPWSTR*)&lpTargetW); - if (lpExeName) - BasepAnsiStringToHeapUnicodeString(lpExeName, (LPWSTR*)&lpExeNameW); + DPRINT1("AddConsoleAliasW entered with lpSource '%S' lpTarget '%S' lpExeName '%S'\n", + lpSource, lpTarget, lpExeName); - bRetVal = AddConsoleAliasW(lpSourceW, lpTargetW, lpExeNameW); - - /* Clean up */ - if (lpSourceW) - RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*)lpSourceW); - if (lpTargetW) - RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*)lpTargetW); - if (lpExeNameW) - RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*)lpExeNameW); - - return bRetVal; + return IntAddConsoleAlias(lpSource, + SourceBufferLength, + lpTarget, + TargetBufferLength, + lpExeName, + TRUE); } /* * @implemented */ -DWORD +BOOL WINAPI -GetConsoleAliasW(LPWSTR lpSource, - LPWSTR lpTargetBuffer, - DWORD TargetBufferLength, - LPWSTR lpExeName) +AddConsoleAliasA(LPCSTR lpSource, + LPCSTR lpTarget, + LPCSTR lpExeName) +{ + USHORT SourceBufferLength = (USHORT)strlen(lpSource) * sizeof(CHAR); + USHORT TargetBufferLength = (USHORT)(lpTarget ? strlen(lpTarget) * sizeof(CHAR) : 0); + + DPRINT1("AddConsoleAliasA entered with lpSource '%s' lpTarget '%s' lpExeName '%s'\n", + lpSource, lpTarget, lpExeName); + + return IntAddConsoleAlias(lpSource, + SourceBufferLength, + lpTarget, + TargetBufferLength, + lpExeName, + FALSE); +} + + +static DWORD +IntGetConsoleAlias(LPVOID Source, + USHORT SourceBufferLength, + LPVOID Target, + USHORT TargetBufferLength, + LPVOID lpExeName, + BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &ApiMessage.Data.ConsoleAliasRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - DPRINT("GetConsoleAliasW entered with lpSource %S lpExeName %S\n", lpSource, lpExeName); + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); - if (lpTargetBuffer == NULL) + if (Source == NULL || Target == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } - /* Determine the needed sizes */ - ConsoleAliasRequest->SourceLength = (wcslen(lpSource ) + 1) * sizeof(WCHAR); - ConsoleAliasRequest->ExeLength = (wcslen(lpExeName) + 1) * sizeof(WCHAR); + if (lpExeName == NULL || NumChars == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + ConsoleAliasRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + + /* Determine the needed sizes */ + ConsoleAliasRequest->SourceLength = SourceBufferLength; + ConsoleAliasRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + ConsoleAliasRequest->Unicode = + ConsoleAliasRequest->Unicode2 = bUnicode; - ConsoleAliasRequest->Target = NULL; ConsoleAliasRequest->TargetLength = TargetBufferLength; /* Allocate a Capture Buffer */ @@ -180,36 +208,39 @@ GetConsoleAliasW(LPWSTR lpSource, /* Capture the strings */ CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpSource, + (PVOID)Source, ConsoleAliasRequest->SourceLength, (PVOID*)&ConsoleAliasRequest->Source); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, ConsoleAliasRequest->ExeLength, - (PVOID*)&ConsoleAliasRequest->Exe); + (PVOID*)&ConsoleAliasRequest->ExeName); /* Allocate space for the target buffer */ CsrAllocateMessagePointer(CaptureBuffer, ConsoleAliasRequest->TargetLength, (PVOID*)&ConsoleAliasRequest->Target); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAlias), - sizeof(CONSOLE_ADDGETALIAS)); - if (!NT_SUCCESS(Status)) + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAlias), + sizeof(*ConsoleAliasRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) { CsrFreeCaptureBuffer(CaptureBuffer); - BaseSetLastNTError(Status); - return 0; + BaseSetLastNTError(ApiMessage.Status); + + if (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL) + return ConsoleAliasRequest->TargetLength; + else + return 0; } /* Copy the returned target string into the user buffer */ - // wcscpy(lpTargetBuffer, ConsoleAliasRequest->Target); - memcpy(lpTargetBuffer, - ConsoleAliasRequest->Target, - ConsoleAliasRequest->TargetLength); + RtlCopyMemory(Target, + ConsoleAliasRequest->Target, + ConsoleAliasRequest->TargetLength); /* Release the capture buffer and exit */ CsrFreeCaptureBuffer(CaptureBuffer); @@ -223,65 +254,20 @@ GetConsoleAliasW(LPWSTR lpSource, */ DWORD WINAPI -GetConsoleAliasA(LPSTR lpSource, - LPSTR lpTargetBuffer, +GetConsoleAliasW(LPWSTR lpSource, + LPWSTR lpTargetBuffer, DWORD TargetBufferLength, - LPSTR lpExeName) + LPWSTR lpExeName) { - LPWSTR lpwSource; - LPWSTR lpwExeName; - LPWSTR lpwTargetBuffer; - UINT dwSourceSize; - UINT dwExeNameSize; - UINT dwResult; + DPRINT1("GetConsoleAliasW entered with lpSource '%S' lpExeName '%S'\n", + lpSource, lpExeName); - DPRINT("GetConsoleAliasA entered\n"); - - if (lpTargetBuffer == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - dwSourceSize = (strlen(lpSource)+1) * sizeof(WCHAR); - lpwSource = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSourceSize); - if (lpwSource == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - MultiByteToWideChar(CP_ACP, 0, lpSource, -1, lpwSource, dwSourceSize); - - dwExeNameSize = (strlen(lpExeName)+1) * sizeof(WCHAR); - lpwExeName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwExeNameSize); - if (lpwExeName == NULL) - { - HeapFree(GetProcessHeap(), 0, lpwSource); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - MultiByteToWideChar(CP_ACP, 0, lpExeName, -1, lpwExeName, dwExeNameSize); - - lpwTargetBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, TargetBufferLength * sizeof(WCHAR)); - if (lpwTargetBuffer == NULL) - { - HeapFree(GetProcessHeap(), 0, lpwSource); - HeapFree(GetProcessHeap(), 0, lpwExeName); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - dwResult = GetConsoleAliasW(lpwSource, lpwTargetBuffer, TargetBufferLength * sizeof(WCHAR), lpwExeName); - - HeapFree(GetProcessHeap(), 0, lpwSource); - HeapFree(GetProcessHeap(), 0, lpwExeName); - - if (dwResult) - dwResult = WideCharToMultiByte(CP_ACP, 0, lpwTargetBuffer, dwResult / sizeof(WCHAR), lpTargetBuffer, TargetBufferLength, NULL, NULL); - - HeapFree(GetProcessHeap(), 0, lpwTargetBuffer); - - return dwResult; + return IntGetConsoleAlias(lpSource, + (USHORT)wcslen(lpSource) * sizeof(WCHAR), + lpTargetBuffer, + TargetBufferLength, + lpExeName, + TRUE); } @@ -290,25 +276,48 @@ GetConsoleAliasA(LPSTR lpSource, */ DWORD WINAPI -GetConsoleAliasesW(LPWSTR AliasBuffer, - DWORD AliasBufferLength, - LPWSTR ExeName) +GetConsoleAliasA(LPSTR lpSource, + LPSTR lpTargetBuffer, + DWORD TargetBufferLength, + LPSTR lpExeName) +{ + DPRINT1("GetConsoleAliasA entered with lpSource '%s' lpExeName '%s'\n", + lpSource, lpExeName); + + return IntGetConsoleAlias(lpSource, + (USHORT)strlen(lpSource) * sizeof(CHAR), + lpTargetBuffer, + TargetBufferLength, + lpExeName, + FALSE); +} + + +static DWORD +IntGetConsoleAliases(LPVOID AliasBuffer, + DWORD AliasBufferLength, + LPVOID lpExeName, + BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETALLALIASES GetAllAliasesRequest = &ApiMessage.Data.GetAllAliasesRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - DPRINT("GetConsoleAliasesW entered\n"); + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); - /* Determine the needed sizes */ - GetAllAliasesRequest->ExeLength = GetConsoleAliasesLengthW(ExeName); - if (GetAllAliasesRequest->ExeLength == 0 || - GetAllAliasesRequest->ExeLength > AliasBufferLength) + if (lpExeName == NULL || NumChars == 0) { + SetLastError(ERROR_INVALID_PARAMETER); return 0; } + GetAllAliasesRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + + /* Determine the needed sizes */ + GetAllAliasesRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + GetAllAliasesRequest->Unicode = + GetAllAliasesRequest->Unicode2 = bUnicode; + GetAllAliasesRequest->AliasesBufferLength = AliasBufferLength; /* Allocate a Capture Buffer */ @@ -323,7 +332,7 @@ GetConsoleAliasesW(LPWSTR AliasBuffer, /* Capture the exe name and allocate space for the aliases buffer */ CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)ExeName, + (PVOID)lpExeName, GetAllAliasesRequest->ExeLength, (PVOID*)&GetAllAliasesRequest->ExeName); @@ -331,26 +340,45 @@ GetConsoleAliasesW(LPWSTR AliasBuffer, GetAllAliasesRequest->AliasesBufferLength, (PVOID*)&GetAllAliasesRequest->AliasesBuffer); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliases), - sizeof(CONSOLE_GETALLALIASES)); - if (!NT_SUCCESS(Status)) + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliases), + sizeof(*GetAllAliasesRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(ApiMessage.Status); return 0; } /* Copy the returned aliases string into the user buffer */ - // wcscpy(AliasBuffer, GetAllAliasesRequest->AliasesBuffer); - memcpy(AliasBuffer, - GetAllAliasesRequest->AliasesBuffer, - GetAllAliasesRequest->AliasesBufferLength); + RtlCopyMemory(AliasBuffer, + GetAllAliasesRequest->AliasesBuffer, + GetAllAliasesRequest->AliasesBufferLength); /* Release the capture buffer and exit */ CsrFreeCaptureBuffer(CaptureBuffer); - return GetAllAliasesRequest->AliasesBufferLength; // / sizeof(WCHAR); (original code) + return GetAllAliasesRequest->AliasesBufferLength; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesW(LPWSTR AliasBuffer, + DWORD AliasBufferLength, + LPWSTR ExeName) +{ + DPRINT1("GetConsoleAliasesW entered with lpExeName '%S'\n", + ExeName); + + return IntGetConsoleAliases(AliasBuffer, + AliasBufferLength, + ExeName, + TRUE); } @@ -363,54 +391,36 @@ GetConsoleAliasesA(LPSTR AliasBuffer, DWORD AliasBufferLength, LPSTR ExeName) { - DWORD dwRetVal = 0; - LPWSTR lpwExeName = NULL; - LPWSTR lpwAliasBuffer; + DPRINT1("GetConsoleAliasesA entered with lpExeName '%s'\n", + ExeName); - DPRINT("GetConsoleAliasesA entered\n"); - - if (ExeName) - BasepAnsiStringToHeapUnicodeString(ExeName, (LPWSTR*)&lpwExeName); - - lpwAliasBuffer = HeapAlloc(GetProcessHeap(), 0, AliasBufferLength * sizeof(WCHAR)); - - dwRetVal = GetConsoleAliasesW(lpwAliasBuffer, AliasBufferLength * sizeof(WCHAR), lpwExeName); - - if (lpwExeName) - RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*)lpwExeName); - - if (dwRetVal) - dwRetVal = WideCharToMultiByte(CP_ACP, 0, lpwAliasBuffer, dwRetVal /**/ / sizeof(WCHAR) /**/, AliasBuffer, AliasBufferLength, NULL, NULL); - - HeapFree(GetProcessHeap(), 0, lpwAliasBuffer); - return dwRetVal; + return IntGetConsoleAliases(AliasBuffer, + AliasBufferLength, + ExeName, + FALSE); } -/* - * @implemented - */ -DWORD -WINAPI -GetConsoleAliasesLengthW(LPWSTR lpExeName) +static DWORD +IntGetConsoleAliasesLength(LPVOID lpExeName, BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest = &ApiMessage.Data.GetAllAliasesLengthRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - DPRINT("GetConsoleAliasesLengthW entered\n"); + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); - if (lpExeName == NULL) + if (lpExeName == NULL || NumChars == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } - GetAllAliasesLengthRequest->ExeLength = (wcslen(lpExeName) + 1) * sizeof(WCHAR); - GetAllAliasesLengthRequest->Length = 0; + GetAllAliasesLengthRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetAllAliasesLengthRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + GetAllAliasesLengthRequest->Unicode = + GetAllAliasesLengthRequest->Unicode2 = bUnicode; - /* Allocate a Capture Buffer */ CaptureBuffer = CsrAllocateCaptureBuffer(1, GetAllAliasesLengthRequest->ExeLength); if (!CaptureBuffer) { @@ -419,22 +429,21 @@ GetConsoleAliasesLengthW(LPWSTR lpExeName) return 0; } - /* Capture the exe name */ CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, GetAllAliasesLengthRequest->ExeLength, (PVOID)&GetAllAliasesLengthRequest->ExeName); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasesLength), - sizeof(CONSOLE_GETALLALIASESLENGTH)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasesLength), + sizeof(*GetAllAliasesLengthRequest)); CsrFreeCaptureBuffer(CaptureBuffer); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return 0; } @@ -447,26 +456,68 @@ GetConsoleAliasesLengthW(LPWSTR lpExeName) */ DWORD WINAPI -GetConsoleAliasesLengthA(LPSTR lpExeName) +GetConsoleAliasesLengthW(LPWSTR lpExeName) { - DWORD dwRetVal = 0; - LPWSTR lpExeNameW = NULL; - - if (lpExeName) - BasepAnsiStringToHeapUnicodeString(lpExeName, (LPWSTR*)&lpExeNameW); - - dwRetVal = GetConsoleAliasesLengthW(lpExeNameW); - if (dwRetVal) - dwRetVal /= sizeof(WCHAR); - - /* Clean up */ - if (lpExeNameW) - RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*)lpExeNameW); - - return dwRetVal; + return IntGetConsoleAliasesLength(lpExeName, TRUE); } +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesLengthA(LPSTR lpExeName) +{ + return IntGetConsoleAliasesLength(lpExeName, FALSE); +} + + +static DWORD +IntGetConsoleAliasExes(PVOID lpExeNameBuffer, + DWORD ExeNameBufferLength, + BOOLEAN bUnicode) +{ + CONSOLE_API_MESSAGE ApiMessage; + PCONSOLE_GETALIASESEXES GetAliasesExesRequest = &ApiMessage.Data.GetAliasesExesRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + + GetAliasesExesRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetAliasesExesRequest->Length = ExeNameBufferLength; + GetAliasesExesRequest->Unicode = bUnicode; + + CaptureBuffer = CsrAllocateCaptureBuffer(1, ExeNameBufferLength); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + CsrAllocateMessagePointer(CaptureBuffer, + ExeNameBufferLength, + (PVOID*)&GetAliasesExesRequest->ExeNames); + + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasExes), + sizeof(*GetAliasesExesRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) + { + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(ApiMessage.Status); + return 0; + } + + RtlCopyMemory(lpExeNameBuffer, + GetAliasesExesRequest->ExeNames, + GetAliasesExesRequest->Length); + + CsrFreeCaptureBuffer(CaptureBuffer); + + return GetAliasesExesRequest->Length; +} + /* * @implemented */ @@ -475,49 +526,8 @@ WINAPI GetConsoleAliasExesW(LPWSTR lpExeNameBuffer, DWORD ExeNameBufferLength) { - NTSTATUS Status; - CONSOLE_API_MESSAGE ApiMessage; - PCONSOLE_GETALIASESEXES GetAliasesExesRequest = &ApiMessage.Data.GetAliasesExesRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - - DPRINT("GetConsoleAliasExesW entered\n"); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, ExeNameBufferLength); - if (!CaptureBuffer) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - GetAliasesExesRequest->Length = ExeNameBufferLength; - - /* Allocate space for the exe name buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - ExeNameBufferLength, - (PVOID*)&GetAliasesExesRequest->ExeNames); - - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasExes), - sizeof(CONSOLE_GETALIASESEXES)); - if (!NT_SUCCESS(Status)) - { - CsrFreeCaptureBuffer(CaptureBuffer); - BaseSetLastNTError(Status); - return 0; - } - - /* Copy the returned target string into the user buffer */ - memcpy(lpExeNameBuffer, - GetAliasesExesRequest->ExeNames, - GetAliasesExesRequest->Length); - - /* Release the capture buffer and exit */ - CsrFreeCaptureBuffer(CaptureBuffer); - - return GetAliasesExesRequest->Length; + DPRINT1("GetConsoleAliasExesW called\n"); + return IntGetConsoleAliasExes(lpExeNameBuffer, ExeNameBufferLength, TRUE); } @@ -529,46 +539,27 @@ WINAPI GetConsoleAliasExesA(LPSTR lpExeNameBuffer, DWORD ExeNameBufferLength) { - LPWSTR lpwExeNameBuffer; - DWORD dwResult; - - DPRINT("GetConsoleAliasExesA entered\n"); - - lpwExeNameBuffer = HeapAlloc(GetProcessHeap(), 0, ExeNameBufferLength * sizeof(WCHAR)); - - dwResult = GetConsoleAliasExesW(lpwExeNameBuffer, ExeNameBufferLength * sizeof(WCHAR)); - - if (dwResult) - dwResult = WideCharToMultiByte(CP_ACP, 0, lpwExeNameBuffer, dwResult / sizeof(WCHAR), lpExeNameBuffer, ExeNameBufferLength, NULL, NULL); - - HeapFree(GetProcessHeap(), 0, lpwExeNameBuffer); - return dwResult; + DPRINT1("GetConsoleAliasExesA called\n"); + return IntGetConsoleAliasExes(lpExeNameBuffer, ExeNameBufferLength, FALSE); } -/* - * @implemented - */ -DWORD -WINAPI -GetConsoleAliasExesLengthW(VOID) +static DWORD +IntGetConsoleAliasExesLength(BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest = &ApiMessage.Data.GetAliasesExesLengthRequest; - DPRINT("GetConsoleAliasExesLengthW entered\n"); + GetAliasesExesLengthRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetAliasesExesLengthRequest->Unicode = bUnicode; - GetAliasesExesLengthRequest->Length = 0; - - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasExesLength), - sizeof(CONSOLE_GETALIASESEXESLENGTH)); - - if (!NT_SUCCESS(Status)) + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetAliasExesLength), + sizeof(*GetAliasesExesLengthRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return 0; } @@ -576,6 +567,18 @@ GetConsoleAliasExesLengthW(VOID) } +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasExesLengthW(VOID) +{ + DPRINT1("GetConsoleAliasExesLengthW called\n"); + return IntGetConsoleAliasExesLength(TRUE); +} + + /* * @implemented */ @@ -583,16 +586,8 @@ DWORD WINAPI GetConsoleAliasExesLengthA(VOID) { - DWORD dwLength; - - DPRINT("GetConsoleAliasExesLengthA entered\n"); - - dwLength = GetConsoleAliasExesLengthW(); - - if (dwLength) - dwLength /= sizeof(WCHAR); - - return dwLength; + DPRINT1("GetConsoleAliasExesLengthA called\n"); + return IntGetConsoleAliasExesLength(FALSE); } /* EOF */ diff --git a/reactos/dll/win32/kernel32/client/console/console.c b/reactos/dll/win32/kernel32/client/console/console.c index 857a30a212c..7ce38ad3f78 100644 --- a/reactos/dll/win32/kernel32/client/console/console.c +++ b/reactos/dll/win32/kernel32/client/console/console.c @@ -1392,15 +1392,29 @@ SetConsoleCursorInfo(HANDLE hConsoleOutput, /*-------------------------------------------------------------- * GetNumberOfConsoleMouseButtons * - * @unimplemented + * @implemented */ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons) { - DPRINT1("GetNumberOfConsoleMouseButtons(0x%p) UNIMPLEMENTED!\n", lpNumberOfMouseButtons); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + 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; } @@ -1496,18 +1510,17 @@ SetConsoleScreenBufferSize(HANDLE hConsoleOutput, static BOOL IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, - const SMALL_RECT *lpScrollRectangle, - const SMALL_RECT *lpClipRectangle, + CONST SMALL_RECT* lpScrollRectangle, + CONST SMALL_RECT* lpClipRectangle, COORD dwDestinationOrigin, - const CHAR_INFO *lpFill, + CONST CHAR_INFO* lpFill, BOOL bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &ApiMessage.Data.ScrollScreenBufferRequest; - ScrollScreenBufferRequest->OutputHandle = hConsoleOutput; - ScrollScreenBufferRequest->Unicode = bUnicode; + ScrollScreenBufferRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ScrollScreenBufferRequest->OutputHandle = hConsoleOutput; ScrollScreenBufferRequest->ScrollRectangle = *lpScrollRectangle; if (lpClipRectangle != NULL) @@ -1521,16 +1534,16 @@ IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, } ScrollScreenBufferRequest->DestinationOrigin = dwDestinationOrigin; - ScrollScreenBufferRequest->Fill = *lpFill; + ScrollScreenBufferRequest->Fill = *lpFill; + ScrollScreenBufferRequest->Unicode = bUnicode; - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer), - sizeof(CONSOLE_SCROLLSCREENBUFFER)); - - if (!NT_SUCCESS(Status)) + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepScrollScreenBuffer), + sizeof(*ScrollScreenBufferRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return FALSE; } @@ -1546,16 +1559,16 @@ IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, BOOL WINAPI ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, - CONST SMALL_RECT *lpScrollRectangle, - CONST SMALL_RECT *lpClipRectangle, + CONST SMALL_RECT* lpScrollRectangle, + CONST SMALL_RECT* lpClipRectangle, COORD dwDestinationOrigin, - CONST CHAR_INFO *lpFill) + CONST CHAR_INFO* lpFill) { return IntScrollConsoleScreenBuffer(hConsoleOutput, - (PSMALL_RECT)lpScrollRectangle, - (PSMALL_RECT)lpClipRectangle, + lpScrollRectangle, + lpClipRectangle, dwDestinationOrigin, - (PCHAR_INFO)lpFill, + lpFill, FALSE); } @@ -1868,14 +1881,16 @@ GetConsoleTitleA(LPSTR lpConsoleTitle, static BOOL -IntSetConsoleTitle(CONST VOID *lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode) +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 = dwNumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + TitleRequest->Length = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); TitleRequest->Unicode = bUnicode; CaptureBuffer = CsrAllocateCaptureBuffer(1, TitleRequest->Length); @@ -1916,7 +1931,7 @@ BOOL WINAPI SetConsoleTitleW(LPCWSTR lpConsoleTitle) { - return IntSetConsoleTitle(lpConsoleTitle, wcslen(lpConsoleTitle), TRUE); + return IntSetConsoleTitle(lpConsoleTitle, TRUE); } @@ -1929,7 +1944,7 @@ BOOL WINAPI SetConsoleTitleA(LPCSTR lpConsoleTitle) { - return IntSetConsoleTitle(lpConsoleTitle, strlen(lpConsoleTitle), FALSE); + return IntSetConsoleTitle(lpConsoleTitle, FALSE); } @@ -2522,14 +2537,6 @@ GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2) return FALSE; } -BOOL -WINAPI -GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode) -{ - STUB; - return FALSE; -} - BOOL WINAPI SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2) @@ -2540,7 +2547,7 @@ SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2) BOOL WINAPI -SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode) { STUB; return FALSE; @@ -2554,6 +2561,14 @@ SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode) return FALSE; } +BOOL +WINAPI +SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; + return FALSE; +} + BOOL WINAPI RegisterConsoleIME(HWND hWnd, LPDWORD ThreadId) diff --git a/reactos/dll/win32/kernel32/client/console/history.c b/reactos/dll/win32/kernel32/client/console/history.c index ae8e93de9a0..2fc50245fb4 100644 --- a/reactos/dll/win32/kernel32/client/console/history.c +++ b/reactos/dll/win32/kernel32/client/console/history.c @@ -16,13 +16,14 @@ /* PRIVATE FUNCTIONS **********************************************************/ +#if 0 /* Get the size needed to copy a string to a capture buffer, including alignment */ static ULONG IntStringSize(LPCVOID String, BOOL Unicode) { ULONG Size = (Unicode ? wcslen(String) : strlen(String)) * sizeof(WCHAR); - return (Size + 3) & -4; + return (Size + 3) & ~3; } @@ -48,67 +49,81 @@ IntCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer, } RequestString->Length = RequestString->MaximumLength = (USHORT)Size; } +#endif - -static BOOL -IntExpungeConsoleCommandHistory(LPCVOID lpExeName, BOOL bUnicode) +static VOID +IntExpungeConsoleCommandHistory(LPCVOID lpExeName, BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &ApiMessage.Data.ExpungeCommandHistoryRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); + + if (lpExeName == NULL || NumChars == 0) { SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + return; } - CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + ExpungeCommandHistoryRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ExpungeCommandHistoryRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + ExpungeCommandHistoryRequest->Unicode = + ExpungeCommandHistoryRequest->Unicode2 = bUnicode; + + // CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + CaptureBuffer = CsrAllocateCaptureBuffer(1, ExpungeCommandHistoryRequest->ExeLength); if (!CaptureBuffer) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; + return; } - IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - &ExpungeCommandHistoryRequest->ExeName); + // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + // &ExpungeCommandHistoryRequest->ExeName); + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpExeName, + ExpungeCommandHistoryRequest->ExeLength, + (PVOID)&ExpungeCommandHistoryRequest->ExeName); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepExpungeCommandHistory), - sizeof(CONSOLE_EXPUNGECOMMANDHISTORY)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepExpungeCommandHistory), + sizeof(*ExpungeCommandHistoryRequest)); CsrFreeCaptureBuffer(CaptureBuffer); - if (!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - return FALSE; - } - - return TRUE; + if (!NT_SUCCESS(ApiMessage.Status)) + BaseSetLastNTError(ApiMessage.Status); } static DWORD -IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName, BOOL bUnicode) +IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName, BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &ApiMessage.Data.GetCommandHistoryRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - DWORD HistoryLength = cbHistory * (bUnicode ? 1 : sizeof(WCHAR)); - if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); + + if (lpExeName == NULL || NumChars == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } - CaptureBuffer = CsrAllocateCaptureBuffer(2, IntStringSize(lpExeName, bUnicode) + - HistoryLength); + GetCommandHistoryRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetCommandHistoryRequest->HistoryLength = cbHistory; + GetCommandHistoryRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + GetCommandHistoryRequest->Unicode = + GetCommandHistoryRequest->Unicode2 = bUnicode; + + // CaptureBuffer = CsrAllocateCaptureBuffer(2, IntStringSize(lpExeName, bUnicode) + + // HistoryLength); + CaptureBuffer = CsrAllocateCaptureBuffer(2, GetCommandHistoryRequest->ExeLength + + GetCommandHistoryRequest->HistoryLength); if (!CaptureBuffer) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); @@ -116,60 +131,60 @@ IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName return 0; } - IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - &GetCommandHistoryRequest->ExeName); - GetCommandHistoryRequest->Length = HistoryLength; - CsrAllocateMessagePointer(CaptureBuffer, HistoryLength, + // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + // &GetCommandHistoryRequest->ExeName); + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpExeName, + GetCommandHistoryRequest->ExeLength, + (PVOID)&GetCommandHistoryRequest->ExeName); + + // CsrAllocateMessagePointer(CaptureBuffer, HistoryLength, + CsrAllocateMessagePointer(CaptureBuffer, GetCommandHistoryRequest->HistoryLength, (PVOID*)&GetCommandHistoryRequest->History); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCommandHistory), - sizeof(CONSOLE_GETCOMMANDHISTORY)); - if (!NT_SUCCESS(Status)) + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCommandHistory), + sizeof(*GetCommandHistoryRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) { CsrFreeCaptureBuffer(CaptureBuffer); - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return 0; } - if (bUnicode) - { - memcpy(lpHistory, - GetCommandHistoryRequest->History, - GetCommandHistoryRequest->Length); - } - else - { - WideCharToMultiByte(CP_ACP, 0, - GetCommandHistoryRequest->History, - GetCommandHistoryRequest->Length / sizeof(WCHAR), - lpHistory, - cbHistory, - NULL, NULL); - } + RtlCopyMemory(lpHistory, + GetCommandHistoryRequest->History, + GetCommandHistoryRequest->HistoryLength); CsrFreeCaptureBuffer(CaptureBuffer); - return GetCommandHistoryRequest->Length; + return GetCommandHistoryRequest->HistoryLength; } static DWORD IntGetConsoleCommandHistoryLength(LPCVOID lpExeName, BOOL bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &ApiMessage.Data.GetCommandHistoryLengthRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); + + if (lpExeName == NULL || NumChars == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } - CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + GetCommandHistoryLengthRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetCommandHistoryLengthRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + GetCommandHistoryLengthRequest->Unicode = + GetCommandHistoryLengthRequest->Unicode2 = bUnicode; + + // CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + CaptureBuffer = CsrAllocateCaptureBuffer(1, GetCommandHistoryLengthRequest->ExeLength); if (!CaptureBuffer) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); @@ -177,43 +192,55 @@ IntGetConsoleCommandHistoryLength(LPCVOID lpExeName, BOOL bUnicode) return 0; } - IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - &GetCommandHistoryLengthRequest->ExeName); + // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + // &GetCommandHistoryLengthRequest->ExeName); + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpExeName, + GetCommandHistoryLengthRequest->ExeLength, + (PVOID)&GetCommandHistoryLengthRequest->ExeName); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCommandHistoryLength), - sizeof(CONSOLE_GETCOMMANDHISTORYLENGTH)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetCommandHistoryLength), + sizeof(*GetCommandHistoryLengthRequest)); CsrFreeCaptureBuffer(CaptureBuffer); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return 0; } - return GetCommandHistoryLengthRequest->Length; + return GetCommandHistoryLengthRequest->HistoryLength; } static BOOL IntSetConsoleNumberOfCommands(DWORD dwNumCommands, LPCVOID lpExeName, - BOOL bUnicode) + BOOLEAN bUnicode) { - NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &ApiMessage.Data.SetHistoryNumberCommandsRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + USHORT NumChars = (USHORT)(lpExeName ? (bUnicode ? wcslen(lpExeName) : strlen(lpExeName)) : 0); + + if (lpExeName == NULL || NumChars == 0) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + SetHistoryNumberCommandsRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + SetHistoryNumberCommandsRequest->NumCommands = dwNumCommands; + SetHistoryNumberCommandsRequest->ExeLength = NumChars * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + SetHistoryNumberCommandsRequest->Unicode = + SetHistoryNumberCommandsRequest->Unicode2 = bUnicode; + + // CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + CaptureBuffer = CsrAllocateCaptureBuffer(1, SetHistoryNumberCommandsRequest->ExeLength); if (!CaptureBuffer) { DPRINT1("CsrAllocateCaptureBuffer failed!\n"); @@ -221,20 +248,23 @@ IntSetConsoleNumberOfCommands(DWORD dwNumCommands, return FALSE; } - IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - &SetHistoryNumberCommandsRequest->ExeName); - SetHistoryNumberCommandsRequest->NumCommands = dwNumCommands; + // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + // &SetHistoryNumberCommandsRequest->ExeName); + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpExeName, + SetHistoryNumberCommandsRequest->ExeLength, + (PVOID)&SetHistoryNumberCommandsRequest->ExeName); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetNumberOfCommands), - sizeof(CONSOLE_SETHISTORYNUMBERCOMMANDS)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetNumberOfCommands), + sizeof(*SetHistoryNumberCommandsRequest)); CsrFreeCaptureBuffer(CaptureBuffer); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(ApiMessage.Status)) { - BaseSetLastNTError(Status); + BaseSetLastNTError(ApiMessage.Status); return FALSE; } @@ -247,22 +277,22 @@ IntSetConsoleNumberOfCommands(DWORD dwNumCommands, /* * @implemented (Undocumented) */ -BOOL +VOID WINAPI ExpungeConsoleCommandHistoryW(LPCWSTR lpExeName) { - return IntExpungeConsoleCommandHistory(lpExeName, TRUE); + IntExpungeConsoleCommandHistory(lpExeName, TRUE); } /* * @implemented (Undocumented) */ -BOOL +VOID WINAPI ExpungeConsoleCommandHistoryA(LPCSTR lpExeName) { - return IntExpungeConsoleCommandHistory(lpExeName, FALSE); + IntExpungeConsoleCommandHistory(lpExeName, FALSE); } @@ -310,7 +340,7 @@ DWORD WINAPI GetConsoleCommandHistoryLengthA(LPCSTR lpExeName) { - return IntGetConsoleCommandHistoryLength(lpExeName, FALSE) / sizeof(WCHAR); + return IntGetConsoleCommandHistoryLength(lpExeName, FALSE); } @@ -320,7 +350,7 @@ GetConsoleCommandHistoryLengthA(LPCSTR lpExeName) BOOL WINAPI SetConsoleNumberOfCommandsW(DWORD dwNumCommands, - LPCSTR lpExeName) + LPCWSTR lpExeName) { return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, TRUE); } @@ -332,21 +362,36 @@ SetConsoleNumberOfCommandsW(DWORD dwNumCommands, BOOL WINAPI SetConsoleNumberOfCommandsA(DWORD dwNumCommands, - LPCWSTR lpExeName) + LPCSTR lpExeName) { return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, FALSE); } /* - * @unimplemented + * @implemented */ BOOL WINAPI SetConsoleCommandHistoryMode(IN DWORD dwMode) { - STUB; - return FALSE; + CONSOLE_API_MESSAGE ApiMessage; + PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &ApiMessage.Data.SetHistoryModeRequest; + + SetHistoryModeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + SetHistoryModeRequest->Mode = dwMode; + + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepSetCommandHistoryMode), + sizeof(*SetHistoryModeRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) + { + BaseSetLastNTError(ApiMessage.Status); + return FALSE; + } + + return TRUE; } /* EOF */ diff --git a/reactos/dll/win32/kernel32/client/console/readwrite.c b/reactos/dll/win32/kernel32/client/console/readwrite.c index d42f8d0a9cb..6dec006a0f4 100644 --- a/reactos/dll/win32/kernel32/client/console/readwrite.c +++ b/reactos/dll/win32/kernel32/client/console/readwrite.c @@ -18,365 +18,593 @@ #include +/* See consrv/include/rect.h */ +#define ConioRectHeight(Rect) \ + (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) +#define ConioRectWidth(Rect) \ + (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) + + /* PRIVATE FUNCTIONS **********************************************************/ /****************** * Read functions * ******************/ +DWORD +WINAPI +GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer); + static BOOL -IntReadConsole(HANDLE hConsoleInput, - PVOID lpBuffer, - DWORD nNumberOfCharsToRead, - LPDWORD lpNumberOfCharsRead, - PCONSOLE_READCONSOLE_CONTROL pInputControl, - BOOL bUnicode) +IntReadConsole(IN HANDLE hConsoleInput, + OUT PVOID lpBuffer, + IN DWORD nNumberOfCharsToRead, + OUT LPDWORD lpNumberOfCharsRead, + IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL, + IN BOOLEAN bUnicode) { - NTSTATUS Status; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_READCONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG CharSize; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + ULONG CharSize, SizeBytes; + + DPRINT("IntReadConsole\n"); + + /* Set up the data to send to the Console Server */ + ReadConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ReadConsoleRequest->InputHandle = hConsoleInput; + ReadConsoleRequest->Unicode = bUnicode; + + /* + * Retrieve the current console executable name string and length (always + * in UNICODE format). + * FIXME: Do not use GetConsoleInputExeNameW but use something else... + */ + // 1- Get the exe name length in characters, including NULL character. + ReadConsoleRequest->ExeLength = + (USHORT)GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer); + // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success). + if (GetConsoleInputExeNameW(ReadConsoleRequest->ExeLength, + (PWCHAR)ReadConsoleRequest->StaticBuffer) != 1) + { + // Nothing + ReadConsoleRequest->ExeLength = 0; + } + else + { + // Remove the NULL character, and convert in number of bytes. + ReadConsoleRequest->ExeLength--; + ReadConsoleRequest->ExeLength *= sizeof(WCHAR); + } + + /*** For DEBUGGING purposes ***/ + { + UNICODE_STRING ExeName; + ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength; + ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer; + DPRINT1("IntReadConsole(ExeName = %wZ)\n", &ExeName); + } + /******************************/ /* Determine the needed size */ - CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); - ReadConsoleRequest->BufferSize = nNumberOfCharsToRead * CharSize; + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + SizeBytes = nNumberOfCharsToRead * CharSize; - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, ReadConsoleRequest->BufferSize); - if (CaptureBuffer == NULL) + ReadConsoleRequest->CaptureBufferSize = + ReadConsoleRequest->NumBytes = SizeBytes; + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are read. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (SizeBytes <= sizeof(ReadConsoleRequest->StaticBuffer)) { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Allocate space in the Buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - ReadConsoleRequest->BufferSize, - (PVOID*)&ReadConsoleRequest->Buffer); - - /* Set up the data to send to the Console Server */ - ReadConsoleRequest->InputHandle = hConsoleInput; - ReadConsoleRequest->Unicode = bUnicode; - ReadConsoleRequest->NrCharactersToRead = nNumberOfCharsToRead; - ReadConsoleRequest->NrCharactersRead = 0; - ReadConsoleRequest->CtrlWakeupMask = 0; - if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) - { - /* - * From MSDN (ReadConsole function), the description - * for pInputControl says: - * "This parameter requires Unicode input by default. - * For ANSI mode, set this parameter to NULL." - */ - ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars; - memcpy(ReadConsoleRequest->Buffer, - lpBuffer, - pInputControl->nInitialChars * sizeof(WCHAR)); - ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; - } - - /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole), - sizeof(CONSOLE_READCONSOLE)); - - /* Check for success */ - if (NT_SUCCESS(Status)) - { - memcpy(lpBuffer, - ReadConsoleRequest->Buffer, - ReadConsoleRequest->NrCharactersRead * CharSize); - - if (lpNumberOfCharsRead != NULL) - *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead; - - if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) - pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState; + ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer; + // CaptureBuffer = NULL; } else { - DPRINT1("CSR returned error in ReadConsole\n"); + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } - if (lpNumberOfCharsRead != NULL) - *lpNumberOfCharsRead = 0; - - /* Error out */ - BaseSetLastNTError(Status); + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + SizeBytes, + (PVOID*)&ReadConsoleRequest->Buffer); } - CsrFreeCaptureBuffer(CaptureBuffer); + ReadConsoleRequest->InitialNumBytes = 0; + ReadConsoleRequest->CtrlWakeupMask = 0; + ReadConsoleRequest->ControlKeyState = 0; - /* Return TRUE or FALSE */ - // return TRUE; - return (ReadConsoleRequest->NrCharactersRead > 0); - // return NT_SUCCESS(Status); + /* + * From MSDN (ReadConsole function), the description + * for pInputControl says: + * "This parameter requires Unicode input by default. + * For ANSI mode, set this parameter to NULL." + */ + _SEH2_TRY + { + if (bUnicode && pInputControl && + pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) + { + /* Sanity check */ + if (pInputControl->nInitialChars <= nNumberOfCharsToRead) + { + ReadConsoleRequest->InitialNumBytes = + pInputControl->nInitialChars * sizeof(WCHAR); // CharSize + + if (pInputControl->nInitialChars != 0) + { + /* + * It is possible here to overwrite the static buffer, in case + * the number of bytes to read was smaller than the static buffer. + * In this case, this means we are continuing a pending read, + * and we do not need in fact the executable name that was + * stored in the static buffer because it was first grabbed when + * we started the first read. + */ + RtlCopyMemory(ReadConsoleRequest->Buffer, + lpBuffer, + ReadConsoleRequest->InitialNumBytes); + } + + ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; + } + else + { + // Status = STATUS_INVALID_PARAMETER; + } + } + else + { + /* We are in a situation where pInputControl has no meaning */ + pInputControl = NULL; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + // HACK + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + /* Check for sanity */ +/* + if (!NT_SUCCESS(Status) && pInputControl) + { + // Free CaptureBuffer if needed + // Set last error to last status + // Return FALSE + } +*/ + + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole), + sizeof(*ReadConsoleRequest)); + + /* Check for success */ + Success = NT_SUCCESS(ApiMessage.Status); + + /* Retrieve the results */ + if (Success) + { + _SEH2_TRY + { + *lpNumberOfCharsRead = ReadConsoleRequest->NumBytes / CharSize; + + if (bUnicode && pInputControl) + pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState; + + RtlCopyMemory(lpBuffer, + ReadConsoleRequest->Buffer, + ReadConsoleRequest->NumBytes); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + if (Success) + { + /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */ + if (ApiMessage.Status == STATUS_ALERTED /* || ApiMessage.Status == STATUS_CANCELLED */) + { + NtYieldExecution(); + SetLastError(ERROR_OPERATION_ABORTED); // STATUS_CANCELLED + } + } + + /* Return success status */ + return Success; } static BOOL -IntGetConsoleInput(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - WORD wFlags, - BOOLEAN bUnicode) +IntGetConsoleInput(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead, + IN WORD wFlags, + IN BOOLEAN bUnicode) { - NTSTATUS Status; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_GETINPUT GetInputRequest = &ApiMessage.Data.GetInputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG Size; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; - if (lpBuffer == NULL) + if (!IsConsoleHandle(hConsoleInput)) { - SetLastError(ERROR_INVALID_PARAMETER); + _SEH2_TRY + { + *lpNumberOfEventsRead = 0; + SetLastError(ERROR_INVALID_HANDLE); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + } + _SEH2_END; + return FALSE; } - Size = nLength * sizeof(INPUT_RECORD); - - DPRINT("IntGetConsoleInput: %lx %p\n", Size, lpNumberOfEventsRead); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Allocate space in the Buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - Size, - (PVOID*)&GetInputRequest->InputRecord); + DPRINT("IntGetConsoleInput: %lx %p\n", nLength, lpNumberOfEventsRead); /* Set up the data to send to the Console Server */ - GetInputRequest->InputHandle = hConsoleInput; - GetInputRequest->InputsRead = 0; - GetInputRequest->Length = nLength; - GetInputRequest->wFlags = wFlags; - GetInputRequest->Unicode = bUnicode; + GetInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetInputRequest->InputHandle = hConsoleInput; + GetInputRequest->NumRecords = nLength; + GetInputRequest->Flags = wFlags; + GetInputRequest->Unicode = bUnicode; - /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput), - sizeof(CONSOLE_GETINPUT)); - DPRINT("Server returned: %x\n", Status); - - /* Check for success */ - if (NT_SUCCESS(Status)) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than five + * input records are read. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (nLength <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) { - /* Return the number of events read */ - DPRINT("Events read: %lx\n", GetInputRequest->InputsRead); - - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = GetInputRequest->InputsRead; - - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - RtlCopyMemory(lpBuffer, - GetInputRequest->InputRecord, - sizeof(INPUT_RECORD) * GetInputRequest->InputsRead); + GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer; + // CaptureBuffer = NULL; } else { - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = 0; + ULONG Size = nLength * sizeof(INPUT_RECORD); - /* Error out */ - BaseSetLastNTError(Status); + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&GetInputRequest->RecordBufPtr); } - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput), + sizeof(*GetInputRequest)); - /* Return TRUE or FALSE */ - return (GetInputRequest->InputsRead > 0); - // return NT_SUCCESS(Status); + /* Check for success */ + Success = NT_SUCCESS(ApiMessage.Status); + + /* Retrieve the results */ + _SEH2_TRY + { + DPRINT("Events read: %lx\n", GetInputRequest->NumRecords); + *lpNumberOfEventsRead = GetInputRequest->NumRecords; + + if (Success) + { + RtlCopyMemory(lpBuffer, + GetInputRequest->RecordBufPtr, + GetInputRequest->NumRecords * sizeof(INPUT_RECORD)); + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return success status */ + return Success; } static BOOL -IntReadConsoleOutput(HANDLE hConsoleOutput, - PCHAR_INFO lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpReadRegion, - BOOL bUnicode) +IntReadConsoleOutput(IN HANDLE hConsoleOutput, + OUT PCHAR_INFO lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpReadRegion, + IN BOOLEAN bUnicode) { + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - DWORD Size, SizeX, SizeY; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; - if (lpBuffer == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); - - DPRINT("IntReadConsoleOutput: %lx %p\n", Size, lpReadRegion); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Allocate space in the Buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - Size, - (PVOID*)&ReadOutputRequest->CharInfo); + SHORT SizeX, SizeY; + ULONG NumCells; /* Set up the data to send to the Console Server */ - ReadOutputRequest->OutputHandle = hConsoleOutput; - ReadOutputRequest->Unicode = bUnicode; - ReadOutputRequest->BufferSize = dwBufferSize; - ReadOutputRequest->BufferCoord = dwBufferCoord; - ReadOutputRequest->ReadRegion = *lpReadRegion; + ReadOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ReadOutputRequest->OutputHandle = hConsoleOutput; + ReadOutputRequest->Unicode = bUnicode; + + /* Update lpReadRegion */ + _SEH2_TRY + { + SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpReadRegion)); + SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpReadRegion)); + if (SizeX <= 0 || SizeY <= 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + _SEH2_YIELD(return FALSE); + } + lpReadRegion->Right = lpReadRegion->Left + SizeX - 1; + lpReadRegion->Bottom = lpReadRegion->Top + SizeY - 1; + + ReadOutputRequest->ReadRegion = *lpReadRegion; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + NumCells = SizeX * SizeY; + DPRINT1("IntReadConsoleOutput: (%d x %d)\n", SizeX, SizeY); + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is read. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (NumCells <= 1) + { + ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer; + // CaptureBuffer = NULL; + } + else + { + ULONG Size = NumCells * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&ReadOutputRequest->CharInfo); + } /* Call the server */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutput), - sizeof(CONSOLE_READOUTPUT)); - DPRINT("Server returned: %x\n", ApiMessage.Status); + sizeof(*ReadOutputRequest)); /* Check for success */ - if (NT_SUCCESS(ApiMessage.Status)) + Success = NT_SUCCESS(ApiMessage.Status); + + /* Retrieve the results */ + _SEH2_TRY { - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - SizeX = ReadOutputRequest->ReadRegion.Right - - ReadOutputRequest->ReadRegion.Left + 1; - SizeY = ReadOutputRequest->ReadRegion.Bottom - - ReadOutputRequest->ReadRegion.Top + 1; - RtlCopyMemory(lpBuffer, - ReadOutputRequest->CharInfo, - sizeof(CHAR_INFO) * SizeX * SizeY); + *lpReadRegion = ReadOutputRequest->ReadRegion; + + if (Success) + { +#if 0 + SHORT x, X; +#endif + SHORT y, Y; + + /* Copy into the buffer */ + + SizeX = ReadOutputRequest->ReadRegion.Right - + ReadOutputRequest->ReadRegion.Left + 1; + + for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y) + { + RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, + ReadOutputRequest->CharInfo + y * SizeX, + SizeX * sizeof(CHAR_INFO)); +#if 0 + for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X) + { + *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) = + *(ReadOutputRequest->CharInfo + y * SizeX + x); + } +#endif + } + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } } - else + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Error out */ - BaseSetLastNTError(ApiMessage.Status); + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; } + _SEH2_END; - /* Return the read region */ - DPRINT("read region: %p\n", ReadOutputRequest->ReadRegion); - *lpReadRegion = ReadOutputRequest->ReadRegion; + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); + /* Return success status */ + return Success; } static BOOL -IntReadConsoleOutputCode(HANDLE hConsoleOutput, - CODE_TYPE CodeType, - PVOID pCode, - DWORD nLength, - COORD dwReadCoord, - LPDWORD lpNumberOfCodesRead) +IntReadConsoleOutputCode(IN HANDLE hConsoleOutput, + IN CODE_TYPE CodeType, + OUT PVOID pCode, + IN DWORD nLength, + IN COORD dwReadCoord, + OUT LPDWORD lpNumberOfCodesRead) { - NTSTATUS Status; - BOOL bRet = TRUE; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG SizeBytes, CodeSize; - DWORD CodesRead; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + ULONG CodeSize, SizeBytes; - /* Determine the needed size */ - switch (CodeType) + DPRINT("IntReadConsoleOutputCode\n"); + + if ( (CodeType != CODE_ASCII ) && + (CodeType != CODE_UNICODE ) && + (CodeType != CODE_ATTRIBUTE) ) { - case CODE_ASCII: - CodeSize = sizeof(CHAR); - break; - - case CODE_UNICODE: - CodeSize = sizeof(WCHAR); - break; - - case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - SizeBytes = nLength * CodeSize; - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - /* Allocate space in the Buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - SizeBytes, - (PVOID*)&ReadOutputCodeRequest->pCode.pCode); + /* Set up the data to send to the Console Server */ + ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ReadOutputCodeRequest->OutputHandle = hConsoleOutput; + ReadOutputCodeRequest->Coord = dwReadCoord; + ReadOutputCodeRequest->NumCodes = nLength; - /* Start reading */ - ReadOutputCodeRequest->OutputHandle = hConsoleOutput; + /* Determine the needed size */ ReadOutputCodeRequest->CodeType = CodeType; - ReadOutputCodeRequest->ReadCoord = dwReadCoord; - - ReadOutputCodeRequest->NumCodesToRead = nLength; - - /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString), - sizeof(CONSOLE_READOUTPUTCODE)); - - /* Check for success */ - if (NT_SUCCESS(Status)) + switch (CodeType) { - CodesRead = ReadOutputCodeRequest->CodesRead; - memcpy(pCode, ReadOutputCodeRequest->pCode.pCode, CodesRead * CodeSize); + case CODE_ASCII: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); + break; - // ReadOutputCodeRequest->ReadCoord = ReadOutputCodeRequest->EndCoord; + case CODE_UNICODE: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); + break; - if (lpNumberOfCodesRead != NULL) - *lpNumberOfCodesRead = CodesRead; + case CODE_ATTRIBUTE: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); + break; + } + SizeBytes = nLength * CodeSize; - bRet = TRUE; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are read. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer)) + { + ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer; + // CaptureBuffer = NULL; } else { - if (lpNumberOfCodesRead != NULL) - *lpNumberOfCodesRead = 0; + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } - /* Error out */ - BaseSetLastNTError(Status); - bRet = FALSE; + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + SizeBytes, + (PVOID*)&ReadOutputCodeRequest->pCode); } - CsrFreeCaptureBuffer(CaptureBuffer); + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString), + sizeof(*ReadOutputCodeRequest)); - return bRet; + /* Check for success */ + Success = NT_SUCCESS(ApiMessage.Status); + + /* Retrieve the results */ + _SEH2_TRY + { + *lpNumberOfCodesRead = ReadOutputCodeRequest->NumCodes; + + if (Success) + { + RtlCopyMemory(pCode, + ReadOutputCodeRequest->pCode, + ReadOutputCodeRequest->NumCodes * CodeSize); + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return success status */ + return Success; } @@ -386,379 +614,539 @@ IntReadConsoleOutputCode(HANDLE hConsoleOutput, static BOOL -IntWriteConsole(HANDLE hConsoleOutput, - PVOID lpBuffer, - DWORD nNumberOfCharsToWrite, - LPDWORD lpNumberOfCharsWritten, +IntWriteConsole(IN HANDLE hConsoleOutput, + IN PVOID lpBuffer, + IN DWORD nNumberOfCharsToWrite, + OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved, - BOOL bUnicode) + IN BOOLEAN bUnicode) { - NTSTATUS Status; - BOOL bRet = TRUE; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG CharSize; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + ULONG CharSize, SizeBytes; + + DPRINT("IntWriteConsole\n"); + + /* Set up the data to send to the Console Server */ + WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + WriteConsoleRequest->OutputHandle = hConsoleOutput; + WriteConsoleRequest->Unicode = bUnicode; + + /* Those members are unused by the client, on Windows */ + WriteConsoleRequest->Reserved1 = 0; + // WriteConsoleRequest->Reserved2 = {0}; /* Determine the needed size */ - CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); - WriteConsoleRequest->BufferSize = nNumberOfCharsToWrite * CharSize; + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + SizeBytes = nNumberOfCharsToWrite * CharSize; - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteConsoleRequest->BufferSize); - if (CaptureBuffer == NULL) + WriteConsoleRequest->NumBytes = SizeBytes; + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are written. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer)) { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } + WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer; + // CaptureBuffer = NULL; + WriteConsoleRequest->UsingStaticBuffer = TRUE; - /* Capture the buffer to write */ - CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpBuffer, - WriteConsoleRequest->BufferSize, - (PVOID*)&WriteConsoleRequest->Buffer); - - /* Start writing */ - WriteConsoleRequest->NrCharactersToWrite = nNumberOfCharsToWrite; - WriteConsoleRequest->OutputHandle = hConsoleOutput; - WriteConsoleRequest->Unicode = bUnicode; - - /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole), - sizeof(CONSOLE_WRITECONSOLE)); - - /* Check for success */ - if (NT_SUCCESS(Status)) - { - if (lpNumberOfCharsWritten != NULL) - *lpNumberOfCharsWritten = WriteConsoleRequest->NrCharactersWritten; - - bRet = TRUE; + _SEH2_TRY + { + RtlCopyMemory(WriteConsoleRequest->Buffer, + lpBuffer, + SizeBytes); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; } else { - if (lpNumberOfCharsWritten != NULL) - *lpNumberOfCharsWritten = 0; + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } - /* Error out */ - BaseSetLastNTError(Status); - bRet = FALSE; + /* Capture the buffer to write */ + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpBuffer, + SizeBytes, + (PVOID*)&WriteConsoleRequest->Buffer); + WriteConsoleRequest->UsingStaticBuffer = FALSE; } - CsrFreeCaptureBuffer(CaptureBuffer); + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole), + sizeof(*WriteConsoleRequest)); - return bRet; + /* Check for success */ + Success = NT_SUCCESS(ApiMessage.Status); + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Retrieve the results */ + if (Success) + { + _SEH2_TRY + { + *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } + + /* Return success status */ + return Success; } static BOOL -IntWriteConsoleInput(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsWritten, - BOOL bUnicode, - BOOL bAppendToEnd) +IntWriteConsoleInput(IN HANDLE hConsoleInput, + IN PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsWritten, + IN BOOLEAN bUnicode, + IN BOOLEAN bAppendToEnd) { + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - DWORD Size; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; - Size = nLength * sizeof(INPUT_RECORD); - - DPRINT("IntWriteConsoleInput: %lx %p\n", Size, lpNumberOfEventsWritten); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Capture the user buffer */ - CsrCaptureMessageBuffer(CaptureBuffer, - lpBuffer, - Size, - (PVOID*)&WriteInputRequest->InputRecord); + DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten); /* Set up the data to send to the Console Server */ - WriteInputRequest->InputHandle = hConsoleInput; - WriteInputRequest->Length = nLength; - WriteInputRequest->Unicode = bUnicode; - WriteInputRequest->AppendToEnd = bAppendToEnd; + WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + WriteInputRequest->InputHandle = hConsoleInput; + WriteInputRequest->NumRecords = nLength; + WriteInputRequest->Unicode = bUnicode; + WriteInputRequest->AppendToEnd = bAppendToEnd; + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than five + * input records are written. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) + { + WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer; + // CaptureBuffer = NULL; + + _SEH2_TRY + { + RtlCopyMemory(WriteInputRequest->RecordBufPtr, + lpBuffer, + nLength * sizeof(INPUT_RECORD)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + } + else + { + ULONG Size = nLength * sizeof(INPUT_RECORD); + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Capture the user buffer */ + CsrCaptureMessageBuffer(CaptureBuffer, + lpBuffer, + Size, + (PVOID*)&WriteInputRequest->RecordBufPtr); + } /* Call the server */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput), - sizeof(CONSOLE_WRITEINPUT)); - DPRINT("Server returned: %x\n", ApiMessage.Status); + sizeof(*WriteInputRequest)); /* Check for success */ - if (NT_SUCCESS(ApiMessage.Status)) + Success = NT_SUCCESS(ApiMessage.Status); + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Retrieve the results */ + _SEH2_TRY { - /* Return the number of events read */ - DPRINT("Events read: %lx\n", WriteInputRequest->Length); + DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords); + *lpNumberOfEventsWritten = WriteInputRequest->NumRecords; - if (lpNumberOfEventsWritten != NULL) - *lpNumberOfEventsWritten = WriteInputRequest->Length; + if (!Success) + BaseSetLastNTError(ApiMessage.Status); } - else + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - if (lpNumberOfEventsWritten != NULL) - *lpNumberOfEventsWritten = 0; - - /* Error out */ - BaseSetLastNTError(ApiMessage.Status); + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; } + _SEH2_END; - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); + /* Return success status */ + return Success; } static BOOL -IntWriteConsoleOutput(HANDLE hConsoleOutput, - CONST CHAR_INFO *lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpWriteRegion, - BOOL bUnicode) +IntWriteConsoleOutput(IN HANDLE hConsoleOutput, + IN CONST CHAR_INFO *lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpWriteRegion, + IN BOOLEAN bUnicode) { + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG Size; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; - if ((lpBuffer == NULL) || (lpWriteRegion == NULL)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - /* - if (lpWriteRegion == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - */ - - Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO); - - DPRINT("IntWriteConsoleOutput: %lx %p\n", Size, lpWriteRegion); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Capture the user buffer */ - CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpBuffer, - Size, - (PVOID*)&WriteOutputRequest->CharInfo); + SHORT SizeX, SizeY; + ULONG NumCells; /* Set up the data to send to the Console Server */ - WriteOutputRequest->OutputHandle = hConsoleOutput; - WriteOutputRequest->Unicode = bUnicode; - WriteOutputRequest->BufferSize = dwBufferSize; - WriteOutputRequest->BufferCoord = dwBufferCoord; - WriteOutputRequest->WriteRegion = *lpWriteRegion; + WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + WriteOutputRequest->OutputHandle = hConsoleOutput; + WriteOutputRequest->Unicode = bUnicode; + + /* Update lpWriteRegion */ + _SEH2_TRY + { + SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion)); + SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion)); + if (SizeX <= 0 || SizeY <= 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + _SEH2_YIELD(return FALSE); + } + lpWriteRegion->Right = lpWriteRegion->Left + SizeX - 1; + lpWriteRegion->Bottom = lpWriteRegion->Top + SizeY - 1; + + WriteOutputRequest->WriteRegion = *lpWriteRegion; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + NumCells = SizeX * SizeY; + DPRINT1("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY); + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is written. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (NumCells <= 1) + { + WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer; + // CaptureBuffer = NULL; + } + else + { + ULONG Size = NumCells * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&WriteOutputRequest->CharInfo); + } + + /* Capture the user buffer contents */ + _SEH2_TRY + { +#if 0 + SHORT x, X; +#endif + SHORT y, Y; + + /* Copy into the buffer */ + + SizeX = WriteOutputRequest->WriteRegion.Right - + WriteOutputRequest->WriteRegion.Left + 1; + + for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y) + { + RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX, + lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, + SizeX * sizeof(CHAR_INFO)); +#if 0 + for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X) + { + *(WriteOutputRequest->CharInfo + y * SizeX + x) = + *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)); + } +#endif + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; /* Call the server */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput), - sizeof(CONSOLE_WRITEOUTPUT)); - DPRINT("Server returned: %x\n", ApiMessage.Status); + sizeof(*WriteOutputRequest)); /* Check for success */ - if (!NT_SUCCESS(ApiMessage.Status)) + Success = NT_SUCCESS(ApiMessage.Status); + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Retrieve the results */ + _SEH2_TRY { - /* Error out */ - BaseSetLastNTError(ApiMessage.Status); + *lpWriteRegion = WriteOutputRequest->WriteRegion; + + if (!Success) + BaseSetLastNTError(ApiMessage.Status); } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; - /* Return the read region */ - DPRINT("read region: %p\n", WriteOutputRequest->WriteRegion); - *lpWriteRegion = WriteOutputRequest->WriteRegion; - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); + /* Return success status */ + return Success; } static BOOL -IntWriteConsoleOutputCode(HANDLE hConsoleOutput, - CODE_TYPE CodeType, - CONST VOID *pCode, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfCodesWritten) +IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput, + IN CODE_TYPE CodeType, + IN CONST VOID *pCode, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfCodesWritten) { - NTSTATUS Status; - BOOL bRet = TRUE; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG CodeSize; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + ULONG CodeSize, SizeBytes; - /* Determine the needed size */ - switch (CodeType) + if ( (CodeType != CODE_ASCII ) && + (CodeType != CODE_UNICODE ) && + (CodeType != CODE_ATTRIBUTE) ) { - case CODE_ASCII: - CodeSize = sizeof(CHAR); - break; - - case CODE_UNICODE: - CodeSize = sizeof(WCHAR); - break; - - case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - WriteOutputCodeRequest->BufferSize = nLength * CodeSize; - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteOutputCodeRequest->BufferSize); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - /* Capture the buffer to write */ - CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)pCode, - WriteOutputCodeRequest->BufferSize, - (PVOID*)&WriteOutputCodeRequest->pCode.pCode); + DPRINT("IntWriteConsoleOutputCode\n"); - /* Start writing */ - WriteOutputCodeRequest->OutputHandle = hConsoleOutput; + /* Set up the data to send to the Console Server */ + WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + WriteOutputCodeRequest->OutputHandle = hConsoleOutput; + WriteOutputCodeRequest->Coord = dwWriteCoord; + WriteOutputCodeRequest->NumCodes = nLength; + + /* Determine the needed size */ WriteOutputCodeRequest->CodeType = CodeType; - WriteOutputCodeRequest->Coord = dwWriteCoord; - - WriteOutputCodeRequest->Length = (USHORT)nLength; - - /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString), - sizeof(CONSOLE_WRITEOUTPUTCODE)); - - /* Check for success */ - if (NT_SUCCESS(Status)) + switch (CodeType) { - // WriteOutputCodeRequest->Coord = WriteOutputCodeRequest->EndCoord; + case CODE_ASCII: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); + break; - if (lpNumberOfCodesWritten != NULL) - // *lpNumberOfCodesWritten = WriteOutputCodeRequest->NrCharactersWritten; - *lpNumberOfCodesWritten = WriteOutputCodeRequest->Length; + case CODE_UNICODE: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); + break; - bRet = TRUE; + case CODE_ATTRIBUTE: + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); + break; + } + SizeBytes = nLength * CodeSize; + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are written. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer)) + { + WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer; + // CaptureBuffer = NULL; + + _SEH2_TRY + { + RtlCopyMemory(WriteOutputCodeRequest->pCode, + pCode, + SizeBytes); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; } else { - if (lpNumberOfCodesWritten != NULL) - *lpNumberOfCodesWritten = 0; + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } - /* Error out */ - BaseSetLastNTError(Status); - bRet = FALSE; + /* Capture the buffer to write */ + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)pCode, + SizeBytes, + (PVOID*)&WriteOutputCodeRequest->pCode); } - CsrFreeCaptureBuffer(CaptureBuffer); + /* Call the server */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString), + sizeof(*WriteOutputCodeRequest)); - return bRet; + /* Check for success */ + Success = NT_SUCCESS(ApiMessage.Status); + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Retrieve the results */ + _SEH2_TRY + { + *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes; + + if (!Success) + BaseSetLastNTError(ApiMessage.Status); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Return success status */ + return Success; } static BOOL -IntFillConsoleOutputCode(HANDLE hConsoleOutput, - CODE_TYPE CodeType, - PVOID pCode, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfCodesWritten) +IntFillConsoleOutputCode(IN HANDLE hConsoleOutput, + IN CODE_TYPE CodeType, + IN CODE_ELEMENT Code, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfCodesWritten) { - NTSTATUS Status; + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest; - FillOutputRequest->OutputHandle = hConsoleOutput; - FillOutputRequest->CodeType = CodeType; + DPRINT("IntFillConsoleOutputCode\n"); - switch (CodeType) + if ( (CodeType != CODE_ASCII ) && + (CodeType != CODE_UNICODE ) && + (CodeType != CODE_ATTRIBUTE) ) { - case CODE_ASCII: - FillOutputRequest->Code.AsciiChar = *(PCHAR)pCode; - break; - - case CODE_UNICODE: - FillOutputRequest->Code.UnicodeChar = *(PWCHAR)pCode; - break; - - case CODE_ATTRIBUTE: - FillOutputRequest->Code.Attribute = *(PWORD)pCode; - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } /* Set up the data to send to the Console Server */ - FillOutputRequest->Coord = dwWriteCoord; - FillOutputRequest->Length = nLength; + FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + FillOutputRequest->OutputHandle = hConsoleOutput; + FillOutputRequest->WriteCoord = dwWriteCoord; + FillOutputRequest->CodeType = CodeType; + FillOutputRequest->Code = Code; + FillOutputRequest->NumCodes = nLength; /* Call the server */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput), - sizeof(CONSOLE_FILLOUTPUTCODE)); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput), + sizeof(*FillOutputRequest)); /* Check for success */ - if (NT_SUCCESS(Status)) - { - if (lpNumberOfCodesWritten != NULL) - *lpNumberOfCodesWritten = FillOutputRequest->Length; - // *lpNumberOfCodesWritten = Request.Data.FillOutputRequest.NrCharactersWritten; + Success = NT_SUCCESS(ApiMessage.Status); - return TRUE; - } - else + /* Retrieve the results */ + _SEH2_TRY { - if (lpNumberOfCodesWritten != NULL) - *lpNumberOfCodesWritten = 0; + *lpNumberOfCodesWritten = FillOutputRequest->NumCodes; - BaseSetLastNTError(Status); - return FALSE; + if (!Success) + BaseSetLastNTError(ApiMessage.Status); } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Return success status */ + return Success; } @@ -775,11 +1163,11 @@ IntFillConsoleOutputCode(HANDLE hConsoleOutput, */ BOOL WINAPI -ReadConsoleW(HANDLE hConsoleInput, - LPVOID lpBuffer, - DWORD nNumberOfCharsToRead, - LPDWORD lpNumberOfCharsRead, - PCONSOLE_READCONSOLE_CONTROL pInputControl) +ReadConsoleW(IN HANDLE hConsoleInput, + OUT LPVOID lpBuffer, + IN DWORD nNumberOfCharsToRead, + OUT LPDWORD lpNumberOfCharsRead, + IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL) { return IntReadConsole(hConsoleInput, lpBuffer, @@ -797,11 +1185,11 @@ ReadConsoleW(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleA(HANDLE hConsoleInput, - LPVOID lpBuffer, - DWORD nNumberOfCharsToRead, - LPDWORD lpNumberOfCharsRead, - PCONSOLE_READCONSOLE_CONTROL pInputControl) +ReadConsoleA(IN HANDLE hConsoleInput, + OUT LPVOID lpBuffer, + IN DWORD nNumberOfCharsToRead, + OUT LPDWORD lpNumberOfCharsRead, + IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL) { return IntReadConsole(hConsoleInput, lpBuffer, @@ -819,10 +1207,10 @@ ReadConsoleA(HANDLE hConsoleInput, */ BOOL WINAPI -PeekConsoleInputW(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead) +PeekConsoleInputW(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -840,10 +1228,10 @@ PeekConsoleInputW(HANDLE hConsoleInput, */ BOOL WINAPI -PeekConsoleInputA(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead) +PeekConsoleInputA(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -861,10 +1249,10 @@ PeekConsoleInputA(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleInputW(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead) +ReadConsoleInputW(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -882,10 +1270,10 @@ ReadConsoleInputW(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleInputA(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead) +ReadConsoleInputA(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -903,11 +1291,11 @@ ReadConsoleInputA(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleInputExW(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - WORD wFlags) +ReadConsoleInputExW(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead, + IN WORD wFlags) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -925,11 +1313,11 @@ ReadConsoleInputExW(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleInputExA(HANDLE hConsoleInput, - PINPUT_RECORD lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsRead, - WORD wFlags) +ReadConsoleInputExA(IN HANDLE hConsoleInput, + OUT PINPUT_RECORD lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsRead, + IN WORD wFlags) { return IntGetConsoleInput(hConsoleInput, lpBuffer, @@ -947,11 +1335,11 @@ ReadConsoleInputExA(HANDLE hConsoleInput, */ BOOL WINAPI -ReadConsoleOutputW(HANDLE hConsoleOutput, - PCHAR_INFO lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpReadRegion) +ReadConsoleOutputW(IN HANDLE hConsoleOutput, + OUT PCHAR_INFO lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpReadRegion) { return IntReadConsoleOutput(hConsoleOutput, lpBuffer, @@ -969,11 +1357,11 @@ ReadConsoleOutputW(HANDLE hConsoleOutput, */ BOOL WINAPI -ReadConsoleOutputA(HANDLE hConsoleOutput, - PCHAR_INFO lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpReadRegion) +ReadConsoleOutputA(IN HANDLE hConsoleOutput, + OUT PCHAR_INFO lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpReadRegion) { return IntReadConsoleOutput(hConsoleOutput, lpBuffer, @@ -991,11 +1379,11 @@ ReadConsoleOutputA(HANDLE hConsoleOutput, */ BOOL WINAPI -ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, - LPWSTR lpCharacter, - DWORD nLength, - COORD dwReadCoord, - LPDWORD lpNumberOfCharsRead) +ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput, + OUT LPWSTR lpCharacter, + IN DWORD nLength, + IN COORD dwReadCoord, + OUT LPDWORD lpNumberOfCharsRead) { return IntReadConsoleOutputCode(hConsoleOutput, CODE_UNICODE, @@ -1013,11 +1401,11 @@ ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, */ BOOL WINAPI -ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, - LPSTR lpCharacter, - DWORD nLength, - COORD dwReadCoord, - LPDWORD lpNumberOfCharsRead) +ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput, + OUT LPSTR lpCharacter, + IN DWORD nLength, + IN COORD dwReadCoord, + OUT LPDWORD lpNumberOfCharsRead) { return IntReadConsoleOutputCode(hConsoleOutput, CODE_ASCII, @@ -1035,11 +1423,11 @@ ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, */ BOOL WINAPI -ReadConsoleOutputAttribute(HANDLE hConsoleOutput, - LPWORD lpAttribute, - DWORD nLength, - COORD dwReadCoord, - LPDWORD lpNumberOfAttrsRead) +ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput, + OUT LPWORD lpAttribute, + IN DWORD nLength, + IN COORD dwReadCoord, + OUT LPDWORD lpNumberOfAttrsRead) { return IntReadConsoleOutputCode(hConsoleOutput, CODE_ATTRIBUTE, @@ -1061,10 +1449,10 @@ ReadConsoleOutputAttribute(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleW(HANDLE hConsoleOutput, - CONST VOID *lpBuffer, - DWORD nNumberOfCharsToWrite, - LPDWORD lpNumberOfCharsWritten, +WriteConsoleW(IN HANDLE hConsoleOutput, + IN CONST VOID *lpBuffer, + IN DWORD nNumberOfCharsToWrite, + OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved) { return IntWriteConsole(hConsoleOutput, @@ -1083,10 +1471,10 @@ WriteConsoleW(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleA(HANDLE hConsoleOutput, - CONST VOID *lpBuffer, - DWORD nNumberOfCharsToWrite, - LPDWORD lpNumberOfCharsWritten, +WriteConsoleA(IN HANDLE hConsoleOutput, + IN CONST VOID *lpBuffer, + IN DWORD nNumberOfCharsToWrite, + OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved) { return IntWriteConsole(hConsoleOutput, @@ -1105,10 +1493,10 @@ WriteConsoleA(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleInputW(HANDLE hConsoleInput, - CONST INPUT_RECORD *lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsWritten) +WriteConsoleInputW(IN HANDLE hConsoleInput, + IN CONST INPUT_RECORD *lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsWritten) { return IntWriteConsoleInput(hConsoleInput, (PINPUT_RECORD)lpBuffer, @@ -1126,10 +1514,10 @@ WriteConsoleInputW(HANDLE hConsoleInput, */ BOOL WINAPI -WriteConsoleInputA(HANDLE hConsoleInput, - CONST INPUT_RECORD *lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsWritten) +WriteConsoleInputA(IN HANDLE hConsoleInput, + IN CONST INPUT_RECORD *lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsWritten) { return IntWriteConsoleInput(hConsoleInput, (PINPUT_RECORD)lpBuffer, @@ -1147,10 +1535,10 @@ WriteConsoleInputA(HANDLE hConsoleInput, */ BOOL WINAPI -WriteConsoleInputVDMW(HANDLE hConsoleInput, - CONST INPUT_RECORD *lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsWritten) +WriteConsoleInputVDMW(IN HANDLE hConsoleInput, + IN CONST INPUT_RECORD *lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsWritten) { return IntWriteConsoleInput(hConsoleInput, (PINPUT_RECORD)lpBuffer, @@ -1168,10 +1556,10 @@ WriteConsoleInputVDMW(HANDLE hConsoleInput, */ BOOL WINAPI -WriteConsoleInputVDMA(HANDLE hConsoleInput, - CONST INPUT_RECORD *lpBuffer, - DWORD nLength, - LPDWORD lpNumberOfEventsWritten) +WriteConsoleInputVDMA(IN HANDLE hConsoleInput, + IN CONST INPUT_RECORD *lpBuffer, + IN DWORD nLength, + OUT LPDWORD lpNumberOfEventsWritten) { return IntWriteConsoleInput(hConsoleInput, (PINPUT_RECORD)lpBuffer, @@ -1189,11 +1577,11 @@ WriteConsoleInputVDMA(HANDLE hConsoleInput, */ BOOL WINAPI -WriteConsoleOutputW(HANDLE hConsoleOutput, - CONST CHAR_INFO *lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpWriteRegion) +WriteConsoleOutputW(IN HANDLE hConsoleOutput, + IN CONST CHAR_INFO *lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpWriteRegion) { return IntWriteConsoleOutput(hConsoleOutput, lpBuffer, @@ -1211,11 +1599,11 @@ WriteConsoleOutputW(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleOutputA(HANDLE hConsoleOutput, - CONST CHAR_INFO *lpBuffer, - COORD dwBufferSize, - COORD dwBufferCoord, - PSMALL_RECT lpWriteRegion) +WriteConsoleOutputA(IN HANDLE hConsoleOutput, + IN CONST CHAR_INFO *lpBuffer, + IN COORD dwBufferSize, + IN COORD dwBufferCoord, + IN OUT PSMALL_RECT lpWriteRegion) { return IntWriteConsoleOutput(hConsoleOutput, lpBuffer, @@ -1233,11 +1621,11 @@ WriteConsoleOutputA(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, - LPCWSTR lpCharacter, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfCharsWritten) +WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput, + IN LPCWSTR lpCharacter, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfCharsWritten) { return IntWriteConsoleOutputCode(hConsoleOutput, CODE_UNICODE, @@ -1255,11 +1643,11 @@ WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, - LPCSTR lpCharacter, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfCharsWritten) +WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput, + IN LPCSTR lpCharacter, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfCharsWritten) { return IntWriteConsoleOutputCode(hConsoleOutput, CODE_ASCII, @@ -1277,11 +1665,11 @@ WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, */ BOOL WINAPI -WriteConsoleOutputAttribute(HANDLE hConsoleOutput, - CONST WORD *lpAttribute, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfAttrsWritten) +WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput, + IN CONST WORD *lpAttribute, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfAttrsWritten) { return IntWriteConsoleOutputCode(hConsoleOutput, CODE_ATTRIBUTE, @@ -1299,15 +1687,17 @@ WriteConsoleOutputAttribute(HANDLE hConsoleOutput, */ BOOL WINAPI -FillConsoleOutputCharacterW(HANDLE hConsoleOutput, - WCHAR cCharacter, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfCharsWritten) +FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput, + IN WCHAR cCharacter, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfCharsWritten) { + CODE_ELEMENT Code; + Code.UnicodeChar = cCharacter; return IntFillConsoleOutputCode(hConsoleOutput, CODE_UNICODE, - &cCharacter, + Code, nLength, dwWriteCoord, lpNumberOfCharsWritten); @@ -1321,15 +1711,17 @@ FillConsoleOutputCharacterW(HANDLE hConsoleOutput, */ BOOL WINAPI -FillConsoleOutputCharacterA(HANDLE hConsoleOutput, - CHAR cCharacter, - DWORD nLength, - COORD dwWriteCoord, +FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput, + IN CHAR cCharacter, + IN DWORD nLength, + IN COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten) { + CODE_ELEMENT Code; + Code.AsciiChar = cCharacter; return IntFillConsoleOutputCode(hConsoleOutput, CODE_ASCII, - &cCharacter, + Code, nLength, dwWriteCoord, lpNumberOfCharsWritten); @@ -1343,15 +1735,17 @@ FillConsoleOutputCharacterA(HANDLE hConsoleOutput, */ BOOL WINAPI -FillConsoleOutputAttribute(HANDLE hConsoleOutput, - WORD wAttribute, - DWORD nLength, - COORD dwWriteCoord, - LPDWORD lpNumberOfAttrsWritten) +FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, + IN WORD wAttribute, + IN DWORD nLength, + IN COORD dwWriteCoord, + OUT LPDWORD lpNumberOfAttrsWritten) { + CODE_ELEMENT Code; + Code.Attribute = wAttribute; return IntFillConsoleOutputCode(hConsoleOutput, CODE_ATTRIBUTE, - &wAttribute, + Code, nLength, dwWriteCoord, lpNumberOfAttrsWritten); diff --git a/reactos/dll/win32/kernel32/client/handle.c b/reactos/dll/win32/kernel32/client/handle.c index 5024f5fef94..3e5cbcf4554 100644 --- a/reactos/dll/win32/kernel32/client/handle.c +++ b/reactos/dll/win32/kernel32/client/handle.c @@ -16,7 +16,6 @@ /* PRIVATE FUNCTIONS **********************************************************/ HANDLE -FASTCALL TranslateStdHandle(IN HANDLE hHandle) { PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; diff --git a/reactos/dll/win32/kernel32/include/console.h b/reactos/dll/win32/kernel32/include/console.h index 8edb3493964..1886608e88e 100644 --- a/reactos/dll/win32/kernel32/include/console.h +++ b/reactos/dll/win32/kernel32/include/console.h @@ -56,7 +56,7 @@ CloseConsoleHandle(HANDLE Handle); HANDLE WINAPI GetConsoleInputWaitHandle(VOID); -HANDLE FASTCALL +HANDLE TranslateStdHandle(HANDLE hHandle); VOID diff --git a/reactos/include/reactos/subsys/csr/csr.h b/reactos/include/reactos/subsys/csr/csr.h index 00338d9769a..e778b11051e 100644 --- a/reactos/include/reactos/subsys/csr/csr.h +++ b/reactos/include/reactos/subsys/csr/csr.h @@ -36,27 +36,33 @@ ULONG NTAPI CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN ULONG MessageLength, - OUT PVOID *CapturedData); + OUT PVOID* CapturedData); VOID NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, - OUT PVOID *CapturedData); - -VOID -NTAPI -CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, - IN LPSTR String OPTIONAL, - IN ULONG StringLength, - IN ULONG MaximumLength, - OUT PANSI_STRING CapturedString); + OUT PVOID* CapturedData); VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer); +VOID +NTAPI +CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, + IN PCSTR String OPTIONAL, + IN ULONG StringLength, + IN ULONG MaximumLength, + OUT PSTRING CapturedString); + +NTSTATUS +NTAPI +CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER* CaptureBuffer, + IN ULONG StringsCount, + IN PUNICODE_STRING* MessageStrings); + PLARGE_INTEGER NTAPI CsrCaptureTimeout(IN ULONG Milliseconds, diff --git a/reactos/include/reactos/subsys/win/conmsg.h b/reactos/include/reactos/subsys/win/conmsg.h index 4d117a717b6..56870f4e94e 100644 --- a/reactos/include/reactos/subsys/win/conmsg.h +++ b/reactos/include/reactos/subsys/win/conmsg.h @@ -218,30 +218,40 @@ typedef struct typedef struct { + HANDLE ConsoleHandle; HANDLE OutputHandle; - BOOL Unicode; - ULONG NrCharactersToWrite; - ULONG NrCharactersWritten; + CHAR StaticBuffer[80]; + PVOID Buffer; // BufPtr + ULONG NumBytes; - ULONG BufferSize; - PVOID Buffer; + // On Windows, the client never uses this member + ULONG Reserved1; + + BOOLEAN UsingStaticBuffer; + BOOLEAN Unicode; + + // On Windows, the client never uses this member + CHAR Reserved2[6]; } CONSOLE_WRITECONSOLE, *PCONSOLE_WRITECONSOLE; typedef struct { + HANDLE ConsoleHandle; HANDLE InputHandle; - BOOL Unicode; - ULONG NrCharactersToRead; - ULONG NrCharactersRead; + USHORT ExeLength; - UNICODE_STRING ExeName; - DWORD CtrlWakeupMask; - DWORD ControlKeyState; + CHAR StaticBuffer[80]; + PVOID Buffer; // BufPtr + ULONG NumBytes; - ULONG BufferSize; - PVOID Buffer; + ULONG CaptureBufferSize; + + ULONG InitialNumBytes; + ULONG CtrlWakeupMask; + ULONG ControlKeyState; + BOOLEAN Unicode; } CONSOLE_READCONSOLE, *PCONSOLE_READCONSOLE; typedef struct @@ -319,6 +329,12 @@ typedef struct */ } CONSOLE_GETSETCURSORINFO, *PCONSOLE_GETSETCURSORINFO; +typedef struct +{ + HANDLE ConsoleHandle; + ULONG NumButtons; +} CONSOLE_GETMOUSEINFO, *PCONSOLE_GETMOUSEINFO; + typedef struct { HANDLE ConsoleHandle; @@ -370,7 +386,8 @@ typedef struct DWORD DesiredAccess; BOOL InheritHandle; DWORD ShareMode; - DWORD ScreenBufferType; /* Type of the screen buffer: CONSOLE_TEXTMODE_BUFFER or CONSOLE_GRAPHICS_BUFFER */ + /* Type of the screen buffer: CONSOLE_TEXTMODE_BUFFER or CONSOLE_GRAPHICS_BUFFER */ + DWORD ScreenBufferType; /* * This structure holds the initialization information * for graphics screen buffers. @@ -405,22 +422,11 @@ typedef struct typedef struct { HANDLE ConsoleHandle; - DWORD Length; + ULONG Length; PVOID Title; BOOLEAN Unicode; } CONSOLE_GETSETCONSOLETITLE, *PCONSOLE_GETSETCONSOLETITLE; -typedef struct -{ - HANDLE OutputHandle; - - BOOL Unicode; - COORD BufferSize; - COORD BufferCoord; - SMALL_RECT WriteRegion; - PCHAR_INFO CharInfo; -} CONSOLE_WRITEOUTPUT, *PCONSOLE_WRITEOUTPUT; - typedef struct { HANDLE ConsoleHandle; @@ -429,14 +435,14 @@ typedef struct typedef struct { - HANDLE OutputHandle; - - BOOL Unicode; + HANDLE ConsoleHandle; + HANDLE OutputHandle; SMALL_RECT ScrollRectangle; - BOOL UseClipRectangle; SMALL_RECT ClipRectangle; - COORD DestinationOrigin; - CHAR_INFO Fill; + BOOL UseClipRectangle; + COORD DestinationOrigin; + CHAR_INFO Fill; + BOOLEAN Unicode; } CONSOLE_SCROLLSCREENBUFFER, *PCONSOLE_SCROLLSCREENBUFFER; @@ -452,100 +458,99 @@ typedef enum _CODE_TYPE CODE_ATTRIBUTE = 0x03 } CODE_TYPE; -typedef struct +typedef union _CODE_ELEMENT { - HANDLE OutputHandle; - - DWORD NumCodesToRead; - COORD ReadCoord; - COORD EndCoord; - - DWORD CodesRead; - - CODE_TYPE CodeType; - union - { - PVOID pCode; - PCHAR AsciiChar; - PWCHAR UnicodeChar; - PWORD Attribute; - } pCode; // Either a pointer to a character or to an attribute. -} CONSOLE_READOUTPUTCODE, *PCONSOLE_READOUTPUTCODE; + CHAR AsciiChar; + WCHAR UnicodeChar; + WORD Attribute; +} CODE_ELEMENT; typedef struct { + HANDLE ConsoleHandle; HANDLE OutputHandle; - - ULONG BufferSize; // Seems unusued - WORD Length; - COORD Coord; - COORD EndCoord; - - ULONG NrCharactersWritten; // Seems unusued + COORD Coord; CODE_TYPE CodeType; - union - { - PVOID pCode; - PCHAR AsciiChar; - PWCHAR UnicodeChar; - PWORD Attribute; - } pCode; // Either a pointer to a character or to an attribute. -} CONSOLE_WRITEOUTPUTCODE, *PCONSOLE_WRITEOUTPUTCODE; + CHAR CodeStaticBuffer[80]; // == 40 * sizeof(CODE_ELEMENT) + PVOID pCode; // Either a pointer to a character or to an attribute. + // union + // { + // PVOID pCode; + // PCHAR AsciiChar; + // PWCHAR UnicodeChar; + // PWORD Attribute; + // } pCode; // Either a pointer to a character or to an attribute. + + ULONG NumCodes; +} CONSOLE_READOUTPUTCODE , *PCONSOLE_READOUTPUTCODE, + CONSOLE_WRITEOUTPUTCODE, *PCONSOLE_WRITEOUTPUTCODE; typedef struct { + HANDLE ConsoleHandle; HANDLE OutputHandle; + COORD WriteCoord; - CODE_TYPE CodeType; - union - { - CHAR AsciiChar; - WCHAR UnicodeChar; - WORD Attribute; - } Code; // Either a character or an attribute. + CODE_TYPE CodeType; + CODE_ELEMENT Code; // Either a character or an attribute. - COORD Coord; - ULONG Length; - - ULONG NrCharactersWritten; // FIXME: Only for chars, is it removable ? + ULONG NumCodes; } CONSOLE_FILLOUTPUTCODE, *PCONSOLE_FILLOUTPUTCODE; typedef struct { - HANDLE InputHandle; - ULONG InputsRead; - PINPUT_RECORD InputRecord; - ULONG Length; - WORD wFlags; - BOOLEAN Unicode; + HANDLE ConsoleHandle; + HANDLE InputHandle; + INPUT_RECORD RecordStaticBuffer[5]; + PINPUT_RECORD RecordBufPtr; + ULONG NumRecords; + WORD Flags; + BOOLEAN Unicode; } CONSOLE_GETINPUT, *PCONSOLE_GETINPUT; typedef struct { - HANDLE OutputHandle; - - BOOL Unicode; - COORD BufferSize; - COORD BufferCoord; - SMALL_RECT ReadRegion; - PCHAR_INFO CharInfo; -} CONSOLE_READOUTPUT, *PCONSOLE_READOUTPUT; - -typedef struct -{ - HANDLE InputHandle; - DWORD Length; - INPUT_RECORD* InputRecord; - BOOL Unicode; - BOOL AppendToEnd; + HANDLE ConsoleHandle; + HANDLE InputHandle; + INPUT_RECORD RecordStaticBuffer[5]; + PINPUT_RECORD RecordBufPtr; + ULONG NumRecords; + BOOLEAN Unicode; + BOOLEAN AppendToEnd; } CONSOLE_WRITEINPUT, *PCONSOLE_WRITEINPUT; +typedef struct +{ + HANDLE ConsoleHandle; + HANDLE OutputHandle; + + CHAR_INFO StaticBuffer; + PCHAR_INFO CharInfo; + + SMALL_RECT ReadRegion; + BOOLEAN Unicode; +} CONSOLE_READOUTPUT, *PCONSOLE_READOUTPUT; + +typedef struct +{ + HANDLE ConsoleHandle; + HANDLE OutputHandle; + + CHAR_INFO StaticBuffer; + PCHAR_INFO CharInfo; + + SMALL_RECT WriteRegion; + BOOLEAN Unicode; + + ULONG Unknown; +} CONSOLE_WRITEOUTPUT, *PCONSOLE_WRITEOUTPUT; + typedef struct { HANDLE ConsoleHandle; HANDLE InputHandle; - DWORD NumberOfEvents; + ULONG NumberOfEvents; } CONSOLE_GETNUMINPUTEVENTS, *PCONSOLE_GETNUMINPUTEVENTS; @@ -656,66 +661,85 @@ typedef struct typedef struct { - ULONG SourceLength; - ULONG TargetLength; // Also used for storing the number of bytes written. - ULONG ExeLength; - LPWSTR Source; - LPWSTR Target; - LPWSTR Exe; + HANDLE ConsoleHandle; + USHORT SourceLength; + USHORT TargetLength; // Also used for storing the number of bytes written. + USHORT ExeLength; + PVOID Source; + PVOID Target; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; } CONSOLE_ADDGETALIAS, *PCONSOLE_ADDGETALIAS; typedef struct { - DWORD ExeLength; - DWORD AliasesBufferLength; - LPWSTR ExeName; - LPWSTR AliasesBuffer; + HANDLE ConsoleHandle; + USHORT ExeLength; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; + ULONG AliasesBufferLength; + PVOID AliasesBuffer; } CONSOLE_GETALLALIASES, *PCONSOLE_GETALLALIASES; typedef struct { - DWORD Length; - DWORD ExeLength; - LPWSTR ExeName; + HANDLE ConsoleHandle; + USHORT ExeLength; + PVOID ExeName; + ULONG Length; + BOOLEAN Unicode; + BOOLEAN Unicode2; } CONSOLE_GETALLALIASESLENGTH, *PCONSOLE_GETALLALIASESLENGTH; typedef struct { - DWORD Length; - LPWSTR ExeNames; + HANDLE ConsoleHandle; + ULONG Length ; // ExeLength; // ExesLength + PVOID ExeNames; + BOOLEAN Unicode; } CONSOLE_GETALIASESEXES, *PCONSOLE_GETALIASESEXES; typedef struct { - DWORD Length; + HANDLE ConsoleHandle; + ULONG Length; + BOOLEAN Unicode; } CONSOLE_GETALIASESEXESLENGTH, *PCONSOLE_GETALIASESEXESLENGTH; typedef struct { - UNICODE_STRING ExeName; - PWCHAR History; - DWORD Length; + HANDLE ConsoleHandle; + ULONG HistoryLength; + PVOID History; + USHORT ExeLength; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; } CONSOLE_GETCOMMANDHISTORY, *PCONSOLE_GETCOMMANDHISTORY; typedef struct { - UNICODE_STRING ExeName; - DWORD Length; + HANDLE ConsoleHandle; + ULONG HistoryLength; + USHORT ExeLength; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; } CONSOLE_GETCOMMANDHISTORYLENGTH, *PCONSOLE_GETCOMMANDHISTORYLENGTH; typedef struct { - UNICODE_STRING ExeName; + HANDLE ConsoleHandle; + USHORT ExeLength; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; } CONSOLE_EXPUNGECOMMANDHISTORY, *PCONSOLE_EXPUNGECOMMANDHISTORY; -typedef struct -{ - UNICODE_STRING ExeName; - DWORD NumCommands; -} CONSOLE_SETHISTORYNUMBERCOMMANDS, *PCONSOLE_SETHISTORYNUMBERCOMMANDS; - typedef struct { UINT HistoryBufferSize; @@ -723,6 +747,22 @@ typedef struct DWORD dwFlags; } CONSOLE_GETSETHISTORYINFO, *PCONSOLE_GETSETHISTORYINFO; +typedef struct +{ + HANDLE ConsoleHandle; + ULONG NumCommands; + USHORT ExeLength; + PVOID ExeName; + BOOLEAN Unicode; + BOOLEAN Unicode2; +} CONSOLE_SETHISTORYNUMBERCOMMANDS, *PCONSOLE_SETHISTORYNUMBERCOMMANDS; + +typedef struct +{ + HANDLE ConsoleHandle; + ULONG Mode; +} CONSOLE_SETHISTORYMODE, *PCONSOLE_SETHISTORYMODE; + typedef struct @@ -781,11 +821,12 @@ typedef struct _CONSOLE_API_MESSAGE CONSOLE_GETHANDLEINFO GetHandleInfoRequest; CONSOLE_SETHANDLEINFO SetHandleInfoRequest; - /* Cursor */ + /* Cursor & Mouse */ CONSOLE_SHOWCURSOR ShowCursorRequest; CONSOLE_SETCURSOR SetCursorRequest; CONSOLE_GETSETCURSORINFO CursorInfoRequest; CONSOLE_SETCURSORPOSITION SetCursorPositionRequest; + CONSOLE_GETMOUSEINFO GetMouseInfoRequest; /* Screen-buffer */ CONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest; @@ -841,8 +882,9 @@ typedef struct _CONSOLE_API_MESSAGE CONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest; CONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest; CONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest; - CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest; CONSOLE_GETSETHISTORYINFO HistoryInfoRequest; + CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest; + CONSOLE_SETHISTORYMODE SetHistoryModeRequest; /* Input and Output Code Pages */ CONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest; diff --git a/reactos/win32ss/user/winsrv/consrv.cmake b/reactos/win32ss/user/winsrv/consrv.cmake index 69dbf469814..63b6f574d7b 100644 --- a/reactos/win32ss/user/winsrv/consrv.cmake +++ b/reactos/win32ss/user/winsrv/consrv.cmake @@ -18,10 +18,11 @@ list(APPEND CONSRV_SOURCE consrv/condrv/coninput.c consrv/condrv/conoutput.c consrv/condrv/console.c - consrv/condrv/dummyfrontend.c + consrv/condrv/dummyterm.c consrv/condrv/graphics.c consrv/condrv/text.c consrv/frontends/input.c + consrv/frontends/terminal.c consrv/frontends/gui/conwnd.c consrv/frontends/gui/fullscreen.c consrv/frontends/gui/guiterm.c diff --git a/reactos/win32ss/user/winsrv/consrv/alias.c b/reactos/win32ss/user/winsrv/consrv/alias.c index a20412fe326..3d7a533d5a0 100644 --- a/reactos/win32ss/user/winsrv/consrv/alias.c +++ b/reactos/win32ss/user/winsrv/consrv/alias.c @@ -18,61 +18,195 @@ typedef struct _ALIAS_ENTRY { - LPCWSTR lpSource; - LPCWSTR lpTarget; + UNICODE_STRING Source; + UNICODE_STRING Target; struct _ALIAS_ENTRY* Next; } ALIAS_ENTRY, *PALIAS_ENTRY; typedef struct _ALIAS_HEADER { - LPCWSTR lpExeName; - PALIAS_ENTRY Data; + UNICODE_STRING ExeName; + PALIAS_ENTRY Data; struct _ALIAS_HEADER* Next; } ALIAS_HEADER, *PALIAS_HEADER; + + +BOOLEAN +ConvertInputAnsiToUnicode(PCONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsUnicode, + PWCHAR* Target, + PUSHORT TargetLength) +{ + ASSERT(Source && Target && TargetLength); + + /* Use the console input CP for the conversion */ + *TargetLength = MultiByteToWideChar(Console->InputCodePage, 0, + Source, SourceLength, + NULL, 0); + *Target = ConsoleAllocHeap(0, *TargetLength * sizeof(WCHAR)); + if (*Target == NULL) return FALSE; + + MultiByteToWideChar(Console->InputCodePage, 0, + Source, SourceLength, + *Target, *TargetLength); + + /* The returned Length was in number of WCHARs, convert it in bytes */ + *TargetLength *= sizeof(WCHAR); + + return TRUE; +} + +BOOLEAN +ConvertInputUnicodeToAnsi(PCONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsAnsi, + PCHAR/* * */ Target, + /*P*/USHORT TargetLength) +{ + ASSERT(Source && Target && TargetLength); + + /* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ + ASSERT((ULONG_PTR)Source != (ULONG_PTR)Target); + + /* Use the console input CP for the conversion */ + // *TargetLength = WideCharToMultiByte(Console->InputCodePage, 0, + // Source, SourceLength, + // NULL, 0, NULL, NULL); + // *Target = ConsoleAllocHeap(0, *TargetLength * sizeof(WCHAR)); + // if (*Target == NULL) return FALSE; + + WideCharToMultiByte(Console->InputCodePage, 0, + Source, SourceLength, + /* * */Target, /* * */TargetLength, + NULL, NULL); + + // /* The returned Length was in number of WCHARs, convert it in bytes */ + // *TargetLength *= sizeof(WCHAR); + + return TRUE; +} + + + + /* PRIVATE FUNCTIONS **********************************************************/ -static -PALIAS_HEADER -IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName) +static PALIAS_HEADER +IntFindAliasHeader(PCONSOLE Console, + PVOID ExeName, + USHORT ExeLength, + BOOLEAN UnicodeExe) { + UNICODE_STRING ExeNameU; + + PALIAS_HEADER RootHeader = Console->Aliases; + INT Diff; + + if (ExeName == NULL) return NULL; + + if (UnicodeExe) + { + ExeNameU.Buffer = ExeName; + /* Length is in bytes */ + ExeNameU.MaximumLength = ExeLength; + } + else + { + if (!ConvertInputAnsiToUnicode(Console, + ExeName, ExeLength, + &ExeNameU.Buffer, &ExeNameU.MaximumLength)) + { + return NULL; + } + } + ExeNameU.Length = ExeNameU.MaximumLength; + while (RootHeader) { - INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName); - if (!diff) return RootHeader; - if (diff > 0) break; + Diff = RtlCompareUnicodeString(&RootHeader->ExeName, &ExeNameU, TRUE); + if (!Diff) + { + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); + return RootHeader; + } + if (Diff > 0) break; RootHeader = RootHeader->Next; } + + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); return NULL; } -PALIAS_HEADER -IntCreateAliasHeader(LPCWSTR lpExeName) +static PALIAS_HEADER +IntCreateAliasHeader(PCONSOLE Console, + PVOID ExeName, + USHORT ExeLength, + BOOLEAN UnicodeExe) { + UNICODE_STRING ExeNameU; + PALIAS_HEADER Entry; - UINT dwLength = wcslen(lpExeName) + 1; - Entry = ConsoleAllocHeap(0, sizeof(ALIAS_HEADER) + sizeof(WCHAR) * dwLength); - if (!Entry) return Entry; + if (ExeName == NULL) return NULL; + + if (UnicodeExe) + { + ExeNameU.Buffer = ExeName; + /* Length is in bytes */ + ExeNameU.MaximumLength = ExeLength; + } + else + { + if (!ConvertInputAnsiToUnicode(Console, + ExeName, ExeLength, + &ExeNameU.Buffer, &ExeNameU.MaximumLength)) + { + return NULL; + } + } + ExeNameU.Length = ExeNameU.MaximumLength; + + Entry = ConsoleAllocHeap(0, sizeof(ALIAS_HEADER) + ExeNameU.Length); + if (!Entry) + { + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); + return Entry; + } + + Entry->ExeName.Buffer = (PWSTR)(Entry + 1); + Entry->ExeName.Length = 0; + Entry->ExeName.MaximumLength = ExeNameU.Length; + RtlCopyUnicodeString(&Entry->ExeName, &ExeNameU); - Entry->lpExeName = (LPCWSTR)(Entry + 1); - wcscpy((PWCHAR)Entry->lpExeName, lpExeName); Entry->Data = NULL; Entry->Next = NULL; + + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); return Entry; } -VOID -IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader) +static VOID +IntInsertAliasHeader(PALIAS_HEADER* RootHeader, + PALIAS_HEADER NewHeader) { PALIAS_HEADER CurrentHeader; PALIAS_HEADER *LastLink = RootHeader; + INT Diff; while ((CurrentHeader = *LastLink) != NULL) { - INT Diff = _wcsicmp(NewHeader->lpExeName, CurrentHeader->lpExeName); + Diff = RtlCompareUnicodeString(&NewHeader->ExeName, &CurrentHeader->ExeName, TRUE); if (Diff < 0) break; LastLink = &CurrentHeader->Next; @@ -82,36 +216,139 @@ IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader) NewHeader->Next = CurrentHeader; } -PALIAS_ENTRY -IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName) +static PALIAS_ENTRY +IntGetAliasEntry(PCONSOLE Console, + PALIAS_HEADER Header, + PVOID Source, + USHORT SourceLength, + BOOLEAN Unicode) { - PALIAS_ENTRY RootHeader; + UNICODE_STRING SourceU; - if (Header == NULL) return NULL; + PALIAS_ENTRY Entry; + INT Diff; - RootHeader = Header->Data; - while (RootHeader) + if (Header == NULL || Source == NULL) return NULL; + + if (Unicode) { - INT diff; - DPRINT("IntGetAliasEntry->lpSource %S\n", RootHeader->lpSource); - diff = _wcsicmp(RootHeader->lpSource, lpSrcName); - if (!diff) return RootHeader; - if (diff > 0) break; - - RootHeader = RootHeader->Next; + SourceU.Buffer = Source; + /* Length is in bytes */ + SourceU.MaximumLength = SourceLength; } + else + { + if (!ConvertInputAnsiToUnicode(Console, + Source, SourceLength, + &SourceU.Buffer, &SourceU.MaximumLength)) + { + return NULL; + } + } + SourceU.Length = SourceU.MaximumLength; + + Entry = Header->Data; + while (Entry) + { + Diff = RtlCompareUnicodeString(&Entry->Source, &SourceU, TRUE); + if (!Diff) + { + if (!Unicode) ConsoleFreeHeap(SourceU.Buffer); + return Entry; + } + if (Diff > 0) break; + + Entry = Entry->Next; + } + + if (!Unicode) ConsoleFreeHeap(SourceU.Buffer); return NULL; } -VOID -IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry) +static PALIAS_ENTRY +IntCreateAliasEntry(PCONSOLE Console, + PVOID Source, + USHORT SourceLength, + PVOID Target, + USHORT TargetLength, + BOOLEAN Unicode) +{ + UNICODE_STRING SourceU; + UNICODE_STRING TargetU; + + PALIAS_ENTRY Entry; + + if (Unicode) + { + SourceU.Buffer = Source; + TargetU.Buffer = Target; + /* Length is in bytes */ + SourceU.MaximumLength = SourceLength; + TargetU.MaximumLength = TargetLength; + } + else + { + if (!ConvertInputAnsiToUnicode(Console, + Source, SourceLength, + &SourceU.Buffer, &SourceU.MaximumLength)) + { + return NULL; + } + + if (!ConvertInputAnsiToUnicode(Console, + Target, TargetLength, + &TargetU.Buffer, &TargetU.MaximumLength)) + { + ConsoleFreeHeap(SourceU.Buffer); + return NULL; + } + } + SourceU.Length = SourceU.MaximumLength; + TargetU.Length = TargetU.MaximumLength; + + Entry = ConsoleAllocHeap(0, sizeof(ALIAS_ENTRY) + + SourceU.Length + TargetU.Length); + if (!Entry) + { + if (!Unicode) + { + ConsoleFreeHeap(TargetU.Buffer); + ConsoleFreeHeap(SourceU.Buffer); + } + return Entry; + } + + Entry->Source.Buffer = (PWSTR)(Entry + 1); + Entry->Source.Length = 0; + Entry->Source.MaximumLength = SourceU.Length; + RtlCopyUnicodeString(&Entry->Source, &SourceU); + + Entry->Target.Buffer = (PWSTR)((ULONG_PTR)Entry->Source.Buffer + Entry->Source.MaximumLength); + Entry->Target.Length = 0; + Entry->Target.MaximumLength = TargetU.Length; + RtlCopyUnicodeString(&Entry->Target, &TargetU); + + Entry->Next = NULL; + + if (!Unicode) + { + ConsoleFreeHeap(TargetU.Buffer); + ConsoleFreeHeap(SourceU.Buffer); + } + return Entry; +} + +static VOID +IntInsertAliasEntry(PALIAS_HEADER Header, + PALIAS_ENTRY NewEntry) { PALIAS_ENTRY CurrentEntry; PALIAS_ENTRY *LastLink = &Header->Data; + INT Diff; while ((CurrentEntry = *LastLink) != NULL) { - INT Diff = _wcsicmp(NewEntry->lpSource, CurrentEntry->lpSource); + Diff = RtlCompareUnicodeString(&NewEntry->Source, &CurrentEntry->Source, TRUE); if (Diff < 0) break; LastLink = &CurrentEntry->Next; @@ -121,120 +358,9 @@ IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry) NewEntry->Next = CurrentEntry; } -PALIAS_ENTRY -IntCreateAliasEntry(LPCWSTR lpSource, LPCWSTR lpTarget) -{ - UINT dwSource; - UINT dwTarget; - PALIAS_ENTRY Entry; - - dwSource = wcslen(lpSource) + 1; - dwTarget = wcslen(lpTarget) + 1; - - Entry = ConsoleAllocHeap(0, sizeof(ALIAS_ENTRY) + sizeof(WCHAR) * (dwSource + dwTarget)); - if (!Entry) return Entry; - - Entry->lpSource = (LPCWSTR)(Entry + 1); - wcscpy((LPWSTR)Entry->lpSource, lpSource); - Entry->lpTarget = Entry->lpSource + dwSource; - wcscpy((LPWSTR)Entry->lpTarget, lpTarget); - Entry->Next = NULL; - - return Entry; -} - -UINT -IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader) -{ - UINT length = 0; - - while (RootHeader) - { - length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR); - RootHeader = RootHeader->Next; - } - if (length) - length += sizeof(WCHAR); // last entry entry is terminated with 2 zero bytes - - return length; -} - -UINT -IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT TargetBufferSize) -{ - UINT Offset = 0; - UINT Length; - - TargetBufferSize /= sizeof(WCHAR); - while (RootHeader) - { - Length = wcslen(RootHeader->lpExeName) + 1; - if (TargetBufferSize > Offset + Length) - { - wcscpy(&TargetBuffer[Offset], RootHeader->lpExeName); - Offset += Length; - } - else - { - break; - } - RootHeader = RootHeader->Next; - } - Length = min(Offset+1, TargetBufferSize); - TargetBuffer[Length] = L'\0'; - return Length * sizeof(WCHAR); -} - -UINT -IntGetAllConsoleAliasesLength(PALIAS_HEADER Header) -{ - UINT Length = 0; - PALIAS_ENTRY CurEntry = Header->Data; - - while (CurEntry) - { - Length += wcslen(CurEntry->lpSource); - Length += wcslen(CurEntry->lpTarget); - Length += 2; // zero byte and '=' - CurEntry = CurEntry->Next; - } - - if (Length) - { - return (Length+1) * sizeof(WCHAR); - } - return 0; -} - -UINT -IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBufferLength) -{ - PALIAS_ENTRY CurEntry = Header->Data; - UINT Offset = 0; - UINT SrcLength, TargetLength; - - TargetBufferLength /= sizeof(WCHAR); - while (CurEntry) - { - SrcLength = wcslen(CurEntry->lpSource) + 1; - TargetLength = wcslen(CurEntry->lpTarget) + 1; - if (Offset + TargetLength + SrcLength >= TargetBufferLength) - break; - - wcscpy(&TargetBuffer[Offset], CurEntry->lpSource); - Offset += SrcLength; - TargetBuffer[Offset] = L'='; - wcscpy(&TargetBuffer[Offset], CurEntry->lpTarget); - Offset += TargetLength; - - CurEntry = CurEntry->Next; - } - TargetBuffer[Offset] = L'\0'; - return Offset * sizeof(WCHAR); -} - -VOID -IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry) +static VOID +IntDeleteAliasEntry(PALIAS_HEADER Header, + PALIAS_ENTRY Entry) { PALIAS_ENTRY *LastLink = &Header->Data; PALIAS_ENTRY CurEntry; @@ -251,6 +377,53 @@ IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry) } } +static UINT +IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader, + BOOLEAN IsUnicode) +{ + UINT Length = 0; + + while (RootHeader) + { + Length += RootHeader->ExeName.Length + sizeof(WCHAR); // NULL-termination + RootHeader = RootHeader->Next; + } + + /* + * Quick and dirty way of getting the number of bytes of the + * corresponding ANSI string from the one in UNICODE. + */ + if (!IsUnicode) + Length /= sizeof(WCHAR); + + return Length; +} + +static UINT +IntGetAllConsoleAliasesLength(PALIAS_HEADER Header, + BOOLEAN IsUnicode) +{ + UINT Length = 0; + PALIAS_ENTRY CurEntry = Header->Data; + + while (CurEntry) + { + Length += CurEntry->Source.Length; + Length += CurEntry->Target.Length; + Length += 2 * sizeof(WCHAR); // '=' and NULL-termination + CurEntry = CurEntry->Next; + } + + /* + * Quick and dirty way of getting the number of bytes of the + * corresponding ANSI string from the one in UNICODE. + */ + if (!IsUnicode) + Length /= sizeof(WCHAR); + + return Length; +} + VOID IntDeleteAllAliases(PCONSOLE Console) { @@ -274,13 +447,14 @@ IntDeleteAllAliases(PCONSOLE Console) CSR_API(SrvAddConsoleAlias) { + NTSTATUS Status; PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest; PCONSOLE Console; PALIAS_HEADER Header; PALIAS_ENTRY Entry; - LPWSTR lpSource, lpTarget, lpExeName; + PVOID lpTarget; - DPRINT("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage); + DPRINT1("SrvAddConsoleAlias entered ApiMessage %p\n", ApiMessage); if ( !CsrValidateMessageBuffer(ApiMessage, (PVOID*)&ConsoleAliasRequest->Source, @@ -291,81 +465,86 @@ CSR_API(SrvAddConsoleAlias) ConsoleAliasRequest->TargetLength, sizeof(BYTE)) || !CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ConsoleAliasRequest->Exe, + (PVOID*)&ConsoleAliasRequest->ExeName, ConsoleAliasRequest->ExeLength, sizeof(BYTE)) ) { return STATUS_INVALID_PARAMETER; } - lpSource = ConsoleAliasRequest->Source; - lpTarget = (ConsoleAliasRequest->TargetLength != 0 ? ConsoleAliasRequest->Target : NULL); - lpExeName = ConsoleAliasRequest->Exe; + lpTarget = (ConsoleAliasRequest->TargetLength != 0 ? ConsoleAliasRequest->Target : NULL); - DPRINT("SrvAddConsoleAlias lpSource %p lpExeName %p lpTarget %p\n", lpSource, lpExeName, lpTarget); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; - if (lpExeName == NULL || lpSource == NULL) - { - return STATUS_INVALID_PARAMETER; - } + Status = STATUS_SUCCESS; - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(ApiMessage->Status)) - { - return ApiMessage->Status; - } - - Header = IntFindAliasHeader(Console->Aliases, lpExeName); + Header = IntFindAliasHeader(Console, + ConsoleAliasRequest->ExeName, + ConsoleAliasRequest->ExeLength, + ConsoleAliasRequest->Unicode2); if (!Header && lpTarget != NULL) { - Header = IntCreateAliasHeader(lpExeName); + Header = IntCreateAliasHeader(Console, + ConsoleAliasRequest->ExeName, + ConsoleAliasRequest->ExeLength, + ConsoleAliasRequest->Unicode2); if (!Header) { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_NO_MEMORY; + goto Quit; } + IntInsertAliasHeader(&Console->Aliases, Header); } if (lpTarget == NULL) // Delete the entry { - Entry = IntGetAliasEntry(Header, lpSource); - if (Entry) + Entry = IntGetAliasEntry(Console, Header, + ConsoleAliasRequest->Source, + ConsoleAliasRequest->SourceLength, + ConsoleAliasRequest->Unicode); + if (!Entry) { - IntDeleteAliasEntry(Header, Entry); - ApiMessage->Status = STATUS_SUCCESS; + Status = STATUS_UNSUCCESSFUL; + goto Quit; } - else - { - ApiMessage->Status = STATUS_INVALID_PARAMETER; - } - ConSrvReleaseConsole(Console, TRUE); - return ApiMessage->Status; + + IntDeleteAliasEntry(Header, Entry); } - - Entry = IntCreateAliasEntry(lpSource, lpTarget); - - if (!Entry) + else // Add the entry { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INSUFFICIENT_RESOURCES; + Entry = IntCreateAliasEntry(Console, + ConsoleAliasRequest->Source, + ConsoleAliasRequest->SourceLength, + ConsoleAliasRequest->Target, + ConsoleAliasRequest->TargetLength, + ConsoleAliasRequest->Unicode); + if (!Entry) + { + Status = STATUS_NO_MEMORY; + goto Quit; + } + + IntInsertAliasEntry(Header, Entry); } - IntInsertAliasEntry(Header, Entry); +Quit: ConSrvReleaseConsole(Console, TRUE); - return STATUS_SUCCESS; + return Status; } CSR_API(SrvGetConsoleAlias) { + NTSTATUS Status; PCONSOLE_ADDGETALIAS ConsoleAliasRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleAliasRequest; PCONSOLE Console; PALIAS_HEADER Header; PALIAS_ENTRY Entry; UINT Length; - LPWSTR lpSource, lpTarget, lpExeName; + PVOID lpTarget; - DPRINT("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage); + DPRINT1("SrvGetConsoleAlias entered ApiMessage %p\n", ApiMessage); if ( !CsrValidateMessageBuffer(ApiMessage, (PVOID*)&ConsoleAliasRequest->Source, @@ -376,19 +555,14 @@ CSR_API(SrvGetConsoleAlias) ConsoleAliasRequest->TargetLength, sizeof(BYTE)) || !CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ConsoleAliasRequest->Exe, + (PVOID*)&ConsoleAliasRequest->ExeName, ConsoleAliasRequest->ExeLength, sizeof(BYTE)) ) { return STATUS_INVALID_PARAMETER; } - lpSource = ConsoleAliasRequest->Source; - lpTarget = ConsoleAliasRequest->Target; - lpExeName = ConsoleAliasRequest->Exe; - - DPRINT("SrvGetConsoleAlias lpExeName %p lpSource %p TargetBuffer %p TargetLength %u\n", - lpExeName, lpSource, lpTarget, ConsoleAliasRequest->TargetLength); + lpTarget = ConsoleAliasRequest->Target; if (ConsoleAliasRequest->ExeLength == 0 || lpTarget == NULL || ConsoleAliasRequest->TargetLength == 0 || ConsoleAliasRequest->SourceLength == 0) @@ -396,46 +570,71 @@ CSR_API(SrvGetConsoleAlias) return STATUS_INVALID_PARAMETER; } - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(ApiMessage->Status)) - { - return ApiMessage->Status; - } + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; - Header = IntFindAliasHeader(Console->Aliases, lpExeName); + Header = IntFindAliasHeader(Console, + ConsoleAliasRequest->ExeName, + ConsoleAliasRequest->ExeLength, + ConsoleAliasRequest->Unicode2); if (!Header) { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INVALID_PARAMETER; + Status = STATUS_UNSUCCESSFUL; + goto Quit; } - Entry = IntGetAliasEntry(Header, lpSource); + Entry = IntGetAliasEntry(Console, Header, + ConsoleAliasRequest->Source, + ConsoleAliasRequest->SourceLength, + ConsoleAliasRequest->Unicode); if (!Entry) { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INVALID_PARAMETER; + Status = STATUS_UNSUCCESSFUL; + goto Quit; } - Length = (wcslen(Entry->lpTarget) + 1) * sizeof(WCHAR); - if (Length > ConsoleAliasRequest->TargetLength) + if (ConsoleAliasRequest->Unicode) { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_BUFFER_TOO_SMALL; + Length = Entry->Target.Length + sizeof(WCHAR); + if (Length > ConsoleAliasRequest->TargetLength) // FIXME: Refine computation. + { + Status = STATUS_BUFFER_TOO_SMALL; + goto Quit; + } + + RtlCopyMemory(lpTarget, Entry->Target.Buffer, Entry->Target.Length); + ConsoleAliasRequest->TargetLength = Length; + } + else + { + Length = (Entry->Target.Length + sizeof(WCHAR)) / sizeof(WCHAR); + if (Length > ConsoleAliasRequest->TargetLength) // FIXME: Refine computation. + { + Status = STATUS_BUFFER_TOO_SMALL; + goto Quit; + } + + ConvertInputUnicodeToAnsi(Console, + Entry->Target.Buffer, Entry->Target.Length, + lpTarget, Entry->Target.Length / sizeof(WCHAR)); + ConsoleAliasRequest->TargetLength = Length; } - wcscpy(lpTarget, Entry->lpTarget); - ConsoleAliasRequest->TargetLength = Length; +Quit: ConSrvReleaseConsole(Console, TRUE); - return STATUS_SUCCESS; + return Status; } CSR_API(SrvGetConsoleAliases) { + NTSTATUS Status; PCONSOLE_GETALLALIASES GetAllAliasesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesRequest; PCONSOLE Console; - ULONG BytesWritten; + ULONG BytesWritten = 0; PALIAS_HEADER Header; + DPRINT1("SrvGetConsoleAliases entered ApiMessage %p\n", ApiMessage); + if ( !CsrValidateMessageBuffer(ApiMessage, (PVOID)&GetAllAliasesRequest->ExeName, GetAllAliasesRequest->ExeLength, @@ -448,45 +647,97 @@ CSR_API(SrvGetConsoleAliases) return STATUS_INVALID_PARAMETER; } - if (GetAllAliasesRequest->ExeName == NULL) + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Header = IntFindAliasHeader(Console, + GetAllAliasesRequest->ExeName, + GetAllAliasesRequest->ExeLength, + GetAllAliasesRequest->Unicode2); + if (!Header) goto Quit; + + if (IntGetAllConsoleAliasesLength(Header, GetAllAliasesRequest->Unicode) > GetAllAliasesRequest->AliasesBufferLength) { - return STATUS_INVALID_PARAMETER; + Status = STATUS_BUFFER_OVERFLOW; + goto Quit; } - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(ApiMessage->Status)) { - return ApiMessage->Status; + LPSTR TargetBufferA; + LPWSTR TargetBufferW; + UINT TargetBufferLength = GetAllAliasesRequest->AliasesBufferLength; + + PALIAS_ENTRY CurEntry = Header->Data; + UINT Offset = 0; + UINT SourceLength, TargetLength; + + if (GetAllAliasesRequest->Unicode) + { + TargetBufferW = GetAllAliasesRequest->AliasesBuffer; + TargetBufferLength /= sizeof(WCHAR); + } + else + { + TargetBufferA = GetAllAliasesRequest->AliasesBuffer; + } + + while (CurEntry) + { + SourceLength = CurEntry->Source.Length / sizeof(WCHAR); + TargetLength = CurEntry->Target.Length / sizeof(WCHAR); + if (Offset + TargetLength + SourceLength + 2 > TargetBufferLength) + { + Status = STATUS_BUFFER_OVERFLOW; + break; + } + + if (GetAllAliasesRequest->Unicode) + { + RtlCopyMemory(&TargetBufferW[Offset], CurEntry->Source.Buffer, SourceLength * sizeof(WCHAR)); + Offset += SourceLength; + TargetBufferW[Offset++] = L'='; + RtlCopyMemory(&TargetBufferW[Offset], CurEntry->Target.Buffer, TargetLength * sizeof(WCHAR)); + Offset += TargetLength; + TargetBufferW[Offset++] = L'\0'; + } + else + { + ConvertInputUnicodeToAnsi(Console, + CurEntry->Source.Buffer, SourceLength * sizeof(WCHAR), + &TargetBufferA[Offset], SourceLength); + Offset += SourceLength; + TargetBufferA[Offset++] = '='; + ConvertInputUnicodeToAnsi(Console, + CurEntry->Target.Buffer, TargetLength * sizeof(WCHAR), + &TargetBufferA[Offset], TargetLength); + Offset += TargetLength; + TargetBufferA[Offset++] = '\0'; + } + + CurEntry = CurEntry->Next; + } + + if (GetAllAliasesRequest->Unicode) + BytesWritten = Offset * sizeof(WCHAR); + else + BytesWritten = Offset; } - Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesRequest->ExeName); - if (!Header) - { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INVALID_PARAMETER; - } - - if (IntGetAllConsoleAliasesLength(Header) > GetAllAliasesRequest->AliasesBufferLength) - { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_BUFFER_OVERFLOW; - } - - BytesWritten = IntGetAllConsoleAliases(Header, - GetAllAliasesRequest->AliasesBuffer, - GetAllAliasesRequest->AliasesBufferLength); - +Quit: GetAllAliasesRequest->AliasesBufferLength = BytesWritten; + ConSrvReleaseConsole(Console, TRUE); - return STATUS_SUCCESS; + return Status; } CSR_API(SrvGetConsoleAliasesLength) { + NTSTATUS Status; PCONSOLE_GETALLALIASESLENGTH GetAllAliasesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAllAliasesLengthRequest; PCONSOLE Console; PALIAS_HEADER Header; - UINT Length; + + DPRINT1("SrvGetConsoleAliasesLength entered ApiMessage %p\n", ApiMessage); if (!CsrValidateMessageBuffer(ApiMessage, (PVOID)&GetAllAliasesLengthRequest->ExeName, @@ -496,89 +747,132 @@ CSR_API(SrvGetConsoleAliasesLength) return STATUS_INVALID_PARAMETER; } - if (GetAllAliasesLengthRequest->ExeName == NULL) + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Header = IntFindAliasHeader(Console, + GetAllAliasesLengthRequest->ExeName, + GetAllAliasesLengthRequest->ExeLength, + GetAllAliasesLengthRequest->Unicode2); + if (Header) { - return STATUS_INVALID_PARAMETER; + GetAllAliasesLengthRequest->Length = + IntGetAllConsoleAliasesLength(Header, + GetAllAliasesLengthRequest->Unicode); + Status = STATUS_SUCCESS; + } + else + { + GetAllAliasesLengthRequest->Length = 0; } - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(ApiMessage->Status)) - { - return ApiMessage->Status; - } - - Header = IntFindAliasHeader(Console->Aliases, GetAllAliasesLengthRequest->ExeName); - if (!Header) - { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INVALID_PARAMETER; - } - - Length = IntGetAllConsoleAliasesLength(Header); - GetAllAliasesLengthRequest->Length = Length; ConSrvReleaseConsole(Console, TRUE); - return STATUS_SUCCESS; + return Status; } CSR_API(SrvGetConsoleAliasExes) { + NTSTATUS Status; PCONSOLE_GETALIASESEXES GetAliasesExesRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesRequest; PCONSOLE Console; - UINT BytesWritten; - UINT ExesLength; + UINT BytesWritten = 0; - DPRINT("SrvGetConsoleAliasExes entered\n"); + DPRINT1("SrvGetConsoleAliasExes entered\n"); if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID)&GetAliasesExesRequest->ExeNames, + (PVOID*)&GetAliasesExesRequest->ExeNames, GetAliasesExesRequest->Length, sizeof(BYTE))) { return STATUS_INVALID_PARAMETER; } - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(ApiMessage->Status)) + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + if (IntGetConsoleAliasesExesLength(Console->Aliases, GetAliasesExesRequest->Unicode) > GetAliasesExesRequest->Length) { - return ApiMessage->Status; + Status = STATUS_BUFFER_OVERFLOW; + goto Quit; } - ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases); - - if (ExesLength > GetAliasesExesRequest->Length) { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_BUFFER_OVERFLOW; + PALIAS_HEADER RootHeader = Console->Aliases; + + LPSTR TargetBufferA; + LPWSTR TargetBufferW; + UINT TargetBufferSize = GetAliasesExesRequest->Length; + + UINT Offset = 0; + UINT Length; + + if (GetAliasesExesRequest->Unicode) + { + TargetBufferW = GetAliasesExesRequest->ExeNames; + TargetBufferSize /= sizeof(WCHAR); + } + else + { + TargetBufferA = GetAliasesExesRequest->ExeNames; + } + + while (RootHeader) + { + Length = RootHeader->ExeName.Length / sizeof(WCHAR); + if (Offset + Length + 1 > TargetBufferSize) + { + Status = STATUS_BUFFER_OVERFLOW; + break; + } + + if (GetAliasesExesRequest->Unicode) + { + RtlCopyMemory(&TargetBufferW[Offset], RootHeader->ExeName.Buffer, Length * sizeof(WCHAR)); + Offset += Length; + TargetBufferW[Offset++] = L'\0'; + } + else + { + ConvertInputUnicodeToAnsi(Console, + RootHeader->ExeName.Buffer, Length * sizeof(WCHAR), + &TargetBufferA[Offset], Length); + Offset += Length; + TargetBufferA[Offset++] = '\0'; + } + + RootHeader = RootHeader->Next; + } + + if (GetAliasesExesRequest->Unicode) + BytesWritten = Offset * sizeof(WCHAR); + else + BytesWritten = Offset; } - if (GetAliasesExesRequest->ExeNames == NULL) - { - ConSrvReleaseConsole(Console, TRUE); - return STATUS_INVALID_PARAMETER; - } - - BytesWritten = IntGetConsoleAliasesExes(Console->Aliases, - GetAliasesExesRequest->ExeNames, - GetAliasesExesRequest->Length); - +Quit: GetAliasesExesRequest->Length = BytesWritten; + ConSrvReleaseConsole(Console, TRUE); - return STATUS_SUCCESS; + return Status; } CSR_API(SrvGetConsoleAliasExesLength) { + NTSTATUS Status; PCONSOLE_GETALIASESEXESLENGTH GetAliasesExesLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetAliasesExesLengthRequest; PCONSOLE Console; - DPRINT("SrvGetConsoleAliasExesLength entered\n"); - ApiMessage->Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (NT_SUCCESS(ApiMessage->Status)) - { - GetAliasesExesLengthRequest->Length = IntGetConsoleAliasesExesLength(Console->Aliases); - ConSrvReleaseConsole(Console, TRUE); - } - return ApiMessage->Status; + DPRINT1("SrvGetConsoleAliasExesLength entered ApiMessage %p\n", ApiMessage); + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + GetAliasesExesLengthRequest->Length = + IntGetConsoleAliasesExesLength(Console->Aliases, + GetAliasesExesLengthRequest->Unicode); + + ConSrvReleaseConsole(Console, TRUE); + return Status; } /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c index afd6a6420a9..4c883eec8e6 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c @@ -16,21 +16,19 @@ /* GLOBALS ********************************************************************/ -#define ConSrvGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \ - ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \ - (Access), (LockConsole), INPUT_BUFFER) -#define ConSrvGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \ - ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \ - (Access), (LockConsole), INPUT_BUFFER) -#define ConSrvReleaseInputBuffer(Buff, IsConsoleLocked) \ - ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked)) - - +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \ - WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \ - MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1) + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1) typedef struct ConsoleInput_t { @@ -41,7 +39,7 @@ typedef struct ConsoleInput_t /* PRIVATE FUNCTIONS **********************************************************/ -static VOID FASTCALL +static VOID ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) { if (InputEvent->EventType == KEY_EVENT) @@ -54,7 +52,7 @@ ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) } } -static VOID FASTCALL +static VOID ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) { if (InputEvent->EventType == KEY_EVENT) @@ -67,78 +65,214 @@ ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) } } -NTSTATUS FASTCALL -ConioAddInputEvent(PCONSOLE Console, - PINPUT_RECORD InputEvent, - BOOLEAN AppendToEnd) -{ - ConsoleInput *ConInRec; - /* Check for pause or unpause */ - if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown) +NTSTATUS +ConDrvAddInputEvents(PCONSOLE Console, + PINPUT_RECORD InputRecords, // InputEvent + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG i = 0; + BOOLEAN SetWaitEvent = FALSE; + + if (NumEventsWritten) *NumEventsWritten = 0; + + /* + * When adding many single events, in the case of repeated mouse move or + * key down events, we try to coalesce them so that we do not saturate + * too quickly the input buffer. + */ + if (NumEventsToWrite == 1 && !IsListEmpty(&Console->InputBuffer.InputEvents)) { - WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode; - if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD)) + PINPUT_RECORD InputRecord = InputRecords; // Only one element + PINPUT_RECORD LastInputRecord; + ConsoleInput* ConInRec; // Input + + /* Get the "next" event of the input buffer */ + if (AppendToEnd) { - DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState; - if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT && - (vk == VK_PAUSE || (vk == 'S' && - (cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && - !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))))) - { - ConioPause(Console, PAUSED_FROM_KEYBOARD); - return STATUS_SUCCESS; - } + /* Get the tail element */ + ConInRec = CONTAINING_RECORD(Console->InputBuffer.InputEvents.Blink, + ConsoleInput, ListEntry); } else { - if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN && - vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL) + /* Get the head element */ + ConInRec = CONTAINING_RECORD(Console->InputBuffer.InputEvents.Flink, + ConsoleInput, ListEntry); + } + LastInputRecord = &ConInRec->InputEvent; + + if (InputRecord->EventType == MOUSE_EVENT && + InputRecord->Event.MouseEvent.dwEventFlags == MOUSE_MOVED) + { + if (LastInputRecord->EventType == MOUSE_EVENT && + LastInputRecord->Event.MouseEvent.dwEventFlags == MOUSE_MOVED) { - ConioUnpause(Console, PAUSED_FROM_KEYBOARD); - return STATUS_SUCCESS; + /* Update the mouse position */ + LastInputRecord->Event.MouseEvent.dwMousePosition.X = + InputRecord->Event.MouseEvent.dwMousePosition.X; + LastInputRecord->Event.MouseEvent.dwMousePosition.Y = + InputRecord->Event.MouseEvent.dwMousePosition.Y; + + i = 1; + // return STATUS_SUCCESS; + Status = STATUS_SUCCESS; + } + } + else if (InputRecord->EventType == KEY_EVENT && + InputRecord->Event.KeyEvent.bKeyDown) + { + if (LastInputRecord->EventType == KEY_EVENT && + LastInputRecord->Event.KeyEvent.bKeyDown && + (LastInputRecord->Event.KeyEvent.wVirtualScanCode == // Same scancode + InputRecord->Event.KeyEvent.wVirtualScanCode) && + (LastInputRecord->Event.KeyEvent.uChar.UnicodeChar == // Same character + InputRecord->Event.KeyEvent.uChar.UnicodeChar) && + (LastInputRecord->Event.KeyEvent.dwControlKeyState == // Same Ctrl/Alt/Shift state + InputRecord->Event.KeyEvent.dwControlKeyState) ) + { + /* Update the repeat count */ + LastInputRecord->Event.KeyEvent.wRepeatCount += + InputRecord->Event.KeyEvent.wRepeatCount; + + i = 1; + // return STATUS_SUCCESS; + Status = STATUS_SUCCESS; } } } - /* Add event to the queue */ - ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput)); - if (ConInRec == NULL) return STATUS_INSUFFICIENT_RESOURCES; + /* If we coalesced the only one element, we can quit */ + if (i == 1 && Status == STATUS_SUCCESS /* && NumEventsToWrite == 1 */) + goto Done; - ConInRec->InputEvent = *InputEvent; + /* + * No event coalesced, add them in the usual way. + */ if (AppendToEnd) { - /* Append the event to the end of the queue */ - InsertTailList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry); + /* Go to the beginning of the list */ + // InputRecords = InputRecords; } else { - /* Append the event to the beginning of the queue */ - InsertHeadList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry); + /* Go to the end of the list */ + InputRecords = &InputRecords[NumEventsToWrite - 1]; } - SetEvent(Console->InputBuffer.ActiveEvent); - CsrNotifyWait(&Console->InputBuffer.ReadWaitQueue, - FALSE, - NULL, - NULL); - if (!IsListEmpty(&Console->InputBuffer.ReadWaitQueue)) + /* Set the event if the list is going to be non-empty */ + if (IsListEmpty(&Console->InputBuffer.InputEvents)) + SetWaitEvent = TRUE; + + for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i) { - CsrDereferenceWait(&Console->InputBuffer.ReadWaitQueue); + PINPUT_RECORD InputRecord; + ConsoleInput* ConInRec; + + if (AppendToEnd) + { + /* Select the event and go to the next one */ + InputRecord = InputRecords++; + } + else + { + /* Select the event and go to the previous one */ + InputRecord = InputRecords--; + } + + /* Add event to the queue */ + ConInRec = ConsoleAllocHeap(0, sizeof(ConsoleInput)); + if (ConInRec == NULL) + { + // return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + continue; + } + + ConInRec->InputEvent = *InputRecord; + + if (AppendToEnd) + { + /* Append the event to the end of the queue */ + InsertTailList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry); + } + else + { + /* Append the event to the beginning of the queue */ + InsertHeadList(&Console->InputBuffer.InputEvents, &ConInRec->ListEntry); + } + + // return STATUS_SUCCESS; + Status = STATUS_SUCCESS; } - return STATUS_SUCCESS; + if (SetWaitEvent) SetEvent(Console->InputBuffer.ActiveEvent); + +Done: + if (NumEventsWritten) *NumEventsWritten = i; + + return Status; } -NTSTATUS FASTCALL + +ULONG +PreprocessInput(PCONSOLE Console, + PINPUT_RECORD InputEvent, + ULONG NumEventsToWrite); +VOID +PostprocessInput(PCONSOLE Console); + +NTSTATUS +ConioAddInputEvents(PCONSOLE Console, + PINPUT_RECORD InputRecords, // InputEvent + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd) +{ + NTSTATUS Status = STATUS_SUCCESS; + + if (NumEventsWritten) *NumEventsWritten = 0; + + /* + * This pre-processing code MUST be IN consrv ONLY!! + */ + NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite); + if (NumEventsToWrite == 0) return STATUS_SUCCESS; + + Status = ConDrvAddInputEvents(Console, + InputRecords, + NumEventsToWrite, + NumEventsWritten, + AppendToEnd); + + /* + * This post-processing code MUST be IN consrv ONLY!! + */ + // if (NT_SUCCESS(Status)) + if (Status == STATUS_SUCCESS) PostprocessInput(Console); + + return Status; +} + +/* Move elsewhere...*/ +NTSTATUS ConioProcessInputEvent(PCONSOLE Console, PINPUT_RECORD InputEvent) { - return ConioAddInputEvent(Console, InputEvent, TRUE); + ULONG NumEventsWritten; + return ConioAddInputEvents(Console, + InputEvent, + 1, + &NumEventsWritten, + TRUE); } -VOID FASTCALL + +VOID PurgeInputBuffer(PCONSOLE Console) { PLIST_ENTRY CurrentEntry; @@ -154,88 +288,13 @@ PurgeInputBuffer(PCONSOLE Console) CloseHandle(Console->InputBuffer.ActiveEvent); } -/* - * This function explicitely references Console->ActiveBuffer - * (and also makes use of keyboard functions...). - * It is possible that it will move into frontends... - */ -VOID NTAPI -ConDrvProcessKey(IN PCONSOLE Console, - IN BOOLEAN Down, - IN UINT VirtualKeyCode, - IN UINT VirtualScanCode, - IN WCHAR UnicodeChar, - IN ULONG ShiftState, - IN BYTE KeyStateCtrl) -{ - INPUT_RECORD er; - - /* process Ctrl-C and Ctrl-Break */ - if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && - Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && - (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) ) - { - DPRINT1("Console_Api Ctrl-C\n"); - ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); - - if (Console->LineBuffer && !Console->LineComplete) - { - /* Line input is in progress; end it */ - Console->LinePos = Console->LineSize = 0; - Console->LineComplete = TRUE; - } - return; - } - - if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && - (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) ) - { - if (!Down) return; - - /* scroll up or down */ - if (VK_UP == VirtualKeyCode) - { - /* only scroll up if there is room to scroll up into */ - if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) - { - Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + - Console->ActiveBuffer->ScreenBufferSize.Y - 1) % - Console->ActiveBuffer->ScreenBufferSize.Y; - Console->ActiveBuffer->CursorPosition.Y++; - } - } - else - { - /* only scroll down if there is room to scroll down into */ - if (Console->ActiveBuffer->CursorPosition.Y != 0) - { - Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % - Console->ActiveBuffer->ScreenBufferSize.Y; - Console->ActiveBuffer->CursorPosition.Y--; - } - } - - ConioDrawConsole(Console); - return; - } - - er.EventType = KEY_EVENT; - er.Event.KeyEvent.bKeyDown = Down; - er.Event.KeyEvent.wRepeatCount = 1; - er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; - er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; - er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; - er.Event.KeyEvent.dwControlKeyState = ShiftState; - - ConioProcessInputEvent(Console, &er); -} - /* PUBLIC DRIVER APIS *********************************************************/ NTSTATUS NTAPI ConDrvReadConsole(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ IN BOOLEAN Unicode, OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, @@ -256,8 +315,7 @@ ConDrvReadConsole(IN PCONSOLE Console, /* Validity checks */ ASSERT(Console == InputBuffer->Header.Console); - ASSERT( (Buffer != NULL && NumCharsToRead >= 0) || - (Buffer == NULL && NumCharsToRead == 0) ); + ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); /* We haven't read anything (yet) */ @@ -268,17 +326,15 @@ ConDrvReadConsole(IN PCONSOLE Console, if (Console->LineBuffer == NULL) { /* Starting a new line */ - Console->LineMaxSize = (WORD)max(256, NumCharsToRead); + Console->LineMaxSize = max(256, NumCharsToRead); Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; - Console->LineComplete = FALSE; - Console->LineUpPressed = FALSE; + Console->LinePos = Console->LineSize = ReadControl->nInitialChars; + Console->LineComplete = Console->LineUpPressed = FALSE; Console->LineInsertToggle = Console->InsertMode; Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; - Console->LineSize = ReadControl->nInitialChars; - Console->LinePos = Console->LineSize; /* * Pre-filling the buffer is only allowed in the Unicode API, @@ -307,7 +363,8 @@ ConDrvReadConsole(IN PCONSOLE Console, if (Input->InputEvent.EventType == KEY_EVENT && Input->InputEvent.Event.KeyEvent.bKeyDown) { - LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent); + LineInputKeyDown(Console, ExeName, + &Input->InputEvent.Event.KeyEvent); ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; } ConsoleFreeHeap(Input); @@ -378,6 +435,7 @@ ConDrvReadConsole(IN PCONSOLE Console, } } + // FIXME: Only set if Status == STATUS_SUCCESS ??? if (NumCharsRead) *NumCharsRead = i; return Status; @@ -402,11 +460,9 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, /* Validity checks */ ASSERT(Console == InputBuffer->Header.Console); - ASSERT( (InputRecord != NULL && NumEventsToRead >= 0) || - (InputRecord == NULL && NumEventsToRead == 0) ); + ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToRead == 0)); - // Do NOT do that !! Use the existing number of events already read, if any... - // if (NumEventsRead) *NumEventsRead = 0; + if (NumEventsRead) *NumEventsRead = 0; if (IsListEmpty(&InputBuffer->InputEvents)) { @@ -419,19 +475,13 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, /* Only get input if there is any */ CurrentInput = InputBuffer->InputEvents.Flink; - if (NumEventsRead) i = *NumEventsRead; // We will read the remaining events... - + i = 0; while ((CurrentInput != &InputBuffer->InputEvents) && (i < NumEventsToRead)) { Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); *InputRecord = Input->InputEvent; - if (!Unicode) - { - ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord); - } - ++InputRecord; ++i; CurrentInput = CurrentInput->Flink; @@ -446,6 +496,15 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, if (NumEventsRead) *NumEventsRead = i; + /* Now translate everything to ANSI */ + if (!Unicode) + { + for (; i > 0; --i) + { + ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord); + } + } + if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); @@ -472,23 +531,26 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console, /* Validity checks */ ASSERT(Console == InputBuffer->Header.Console); - ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) || - (InputRecord == NULL && NumEventsToWrite == 0) ); + ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToWrite == 0)); - // Do NOT do that !! Use the existing number of events already written, if any... - // if (NumEventsWritten) *NumEventsWritten = 0; - - for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite && NT_SUCCESS(Status); ++i) + /* First translate everything to UNICODE */ + if (!Unicode) { - if (!Unicode) + for (i = 0; i < NumEventsToWrite; ++i) { - ConioInputEventToUnicode(Console, InputRecord); + ConioInputEventToUnicode(Console, &InputRecord[i]); } - - Status = ConioAddInputEvent(Console, InputRecord++, AppendToEnd); } - if (NumEventsWritten) *NumEventsWritten = i; + /* Now, add the events */ + // if (NumEventsWritten) *NumEventsWritten = 0; + // ConDrvAddInputEvents + Status = ConioAddInputEvents(Console, + InputRecord, + NumEventsToWrite, + NumEventsWritten, + AppendToEnd); + // if (NumEventsWritten) *NumEventsWritten = i; return Status; } diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c b/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c index 6da44a814aa..42d5cbfdb36 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c @@ -34,6 +34,7 @@ GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer); NTSTATUS CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, + IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl, IN SIZE_T Size) { if (Buffer == NULL || Console == NULL) @@ -44,7 +45,7 @@ CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, /* Initialize the header with the default type */ ConSrvInitObject(&(*Buffer)->Header, SCREEN_BUFFER, Console); - (*Buffer)->Vtbl = NULL; + (*Buffer)->Vtbl = Vtbl; return STATUS_SUCCESS; } @@ -74,7 +75,7 @@ CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer) } // ConDrvCreateConsoleScreenBuffer -NTSTATUS FASTCALL +NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, IN ULONG BufferType, @@ -151,7 +152,7 @@ ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) CONSOLE_SCREEN_BUFFER_Destroy(Buffer); } -VOID FASTCALL +VOID ConioDrawConsole(PCONSOLE Console) { SMALL_RECT Region; @@ -159,7 +160,8 @@ ConioDrawConsole(PCONSOLE Console) if (ActiveBuffer) { - ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); + ConioInitRect(&Region, 0, 0, + ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); TermDrawRegion(Console, &Region); } } diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/console.c b/reactos/win32ss/user/winsrv/consrv/condrv/console.c index 47c1e2aea9b..b0f7099cc6a 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/console.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/console.c @@ -12,20 +12,18 @@ #include -#include #include #define NDEBUG #include -// FIXME: Add this prototype to winternl.h / rtlfuncs.h / ... -NTSTATUS NTAPI RtlGetLastNtStatus(VOID); - /* GLOBALS ********************************************************************/ -static ULONG ConsoleListSize; -static PCONSOLE* ConsoleList; /* The list of all the allocated consoles */ +static ULONG CurrentConsoleID = 0; + +/* Linked list of consoles */ +static LIST_ENTRY ConsoleList; static RTL_RESOURCE ListLock; #define ConDrvLockConsoleListExclusive() \ @@ -37,6 +35,47 @@ static RTL_RESOURCE ListLock; #define ConDrvUnlockConsoleList() \ RtlReleaseResource(&ListLock) + +static NTSTATUS +InsertConsole(IN PCONSOLE Console) +{ + ASSERT(Console); + + /* All went right, so add the console to the list */ + ConDrvLockConsoleListExclusive(); + + DPRINT1("Insert in the list\n"); + InsertTailList(&ConsoleList, &Console->ListEntry); + + // FIXME: Move this code to the caller function!! + /* Get a new console ID */ + _InterlockedExchange((PLONG)&Console->ConsoleID, CurrentConsoleID); + _InterlockedIncrement((PLONG)&CurrentConsoleID); + + /* Unlock the console list and return success */ + ConDrvUnlockConsoleList(); + return STATUS_SUCCESS; +} + +static NTSTATUS +RemoveConsole(IN PCONSOLE Console) +{ + // ASSERT(Console); + if (!Console) return STATUS_INVALID_PARAMETER; + + /* Remove the console from the list */ + ConDrvLockConsoleListExclusive(); + + RemoveEntryList(&Console->ListEntry); + + /* Unlock the console list and return success */ + ConDrvUnlockConsoleList(); + return STATUS_SUCCESS; +} + + +/* PRIVATE FUNCTIONS **********************************************************/ + // Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180 static BOOLEAN ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest, @@ -66,219 +105,21 @@ ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString) } } - -static NTSTATUS -InsertConsole(OUT PHANDLE Handle, - IN PCONSOLE Console) +VOID NTAPI +ConDrvPause(PCONSOLE Console) { -#define CONSOLE_HANDLES_INCREMENT 2 * 3 - - NTSTATUS Status = STATUS_SUCCESS; - ULONG i = 0; - PCONSOLE* Block; - - ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || - (ConsoleList != NULL && ConsoleListSize != 0) ); - - /* All went right, so add the console to the list */ - ConDrvLockConsoleListExclusive(); - DPRINT1("Insert in the list\n"); - - if (ConsoleList) - { - for (i = 0; i < ConsoleListSize; i++) - { - if (ConsoleList[i] == NULL) break; - } - } - - if (i >= ConsoleListSize) - { - DPRINT1("Creation of a new handles table\n"); - /* Allocate a new handles table */ - Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY, - (ConsoleListSize + - CONSOLE_HANDLES_INCREMENT) * sizeof(PCONSOLE)); - if (Block == NULL) - { - Status = STATUS_UNSUCCESSFUL; - goto Quit; - } - - /* If we previously had a handles table, free it and use the new one */ - if (ConsoleList) - { - /* Copy the handles from the old table to the new one */ - RtlCopyMemory(Block, - ConsoleList, - ConsoleListSize * sizeof(PCONSOLE)); - ConsoleFreeHeap(ConsoleList); - } - ConsoleList = Block; - ConsoleListSize += CONSOLE_HANDLES_INCREMENT; - } - - ConsoleList[i] = Console; - *Handle = ULongToHandle((i << 2) | 0x3); - -Quit: - /* Unlock the console list and return status */ - ConDrvUnlockConsoleList(); - return Status; -} - -/* Unused */ -#if 0 -static NTSTATUS -RemoveConsoleByHandle(IN HANDLE Handle) -{ - NTSTATUS Status = STATUS_SUCCESS; - PCONSOLE Console; - - BOOLEAN ValidHandle = ((HandleToULong(Handle) & 0x3) == 0x3); - ULONG Index = HandleToULong(Handle) >> 2; - - if (!ValidHandle) return STATUS_INVALID_HANDLE; - - ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || - (ConsoleList != NULL && ConsoleListSize != 0) ); - - /* Remove the console from the list */ - ConDrvLockConsoleListExclusive(); - - if (Index >= ConsoleListSize || - (Console = ConsoleList[Index]) == NULL) - { - Status = STATUS_INVALID_HANDLE; - goto Quit; - } - - ConsoleList[Index] = NULL; - -Quit: - /* Unlock the console list and return status */ - ConDrvUnlockConsoleList(); - return Status; -} -#endif - -static NTSTATUS -RemoveConsoleByPointer(IN PCONSOLE Console) -{ - ULONG i = 0; - - if (!Console) return STATUS_INVALID_PARAMETER; - - ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || - (ConsoleList != NULL && ConsoleListSize != 0) ); - - /* Remove the console from the list */ - ConDrvLockConsoleListExclusive(); - - if (ConsoleList) - { - for (i = 0; i < ConsoleListSize; i++) - { - if (ConsoleList[i] == Console) ConsoleList[i] = NULL; - } - } - - /* Unlock the console list */ - ConDrvUnlockConsoleList(); - - return STATUS_SUCCESS; -} - - -/* For resetting the frontend - defined in dummyfrontend.c */ -VOID ResetFrontEnd(IN PCONSOLE Console); - - -/* PRIVATE FUNCTIONS **********************************************************/ - -static NTSTATUS -ConDrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, - IN PCONSOLE_PROCESS_DATA ProcessData, - IN ULONG Timeout) -{ - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("ConDrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess); - - if (ProcessData->CtrlDispatcher) - { - _SEH2_TRY - { - HANDLE Thread = NULL; - - _SEH2_TRY - { - Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, - ProcessData->CtrlDispatcher, - UlongToPtr(CtrlEvent), 0, NULL); - if (NULL == Thread) - { - Status = RtlGetLastNtStatus(); - DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status); - } - else - { - DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); - WaitForSingleObject(Thread, Timeout); - } - } - _SEH2_FINALLY - { - CloseHandle(Thread); - } - _SEH2_END; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - DPRINT1("ConDrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status); - } - _SEH2_END; - } - - return Status; -} - -NTSTATUS -ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent, - IN PCONSOLE_PROCESS_DATA ProcessData) -{ - return ConDrvConsoleCtrlEventTimeout(CtrlEvent, ProcessData, 0); -} - -VOID FASTCALL -ConioPause(PCONSOLE Console, UINT Flags) -{ - Console->PauseFlags |= Flags; if (!Console->UnpauseEvent) Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } -VOID FASTCALL -ConioUnpause(PCONSOLE Console, UINT Flags) +VOID NTAPI +ConDrvUnpause(PCONSOLE Console) { - Console->PauseFlags &= ~Flags; - - // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0) - if (Console->PauseFlags == 0 && Console->UnpauseEvent) + if (Console->UnpauseEvent) { SetEvent(Console->UnpauseEvent); CloseHandle(Console->UnpauseEvent); Console->UnpauseEvent = NULL; - - CsrNotifyWait(&Console->WriteWaitQueue, - TRUE, - NULL, - NULL); - if (!IsListEmpty(&Console->WriteWaitQueue)) - { - CsrDereferenceWait(&Console->WriteWaitQueue); - } } } @@ -326,103 +167,6 @@ ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, return TRUE; } -BOOLEAN NTAPI -ConDrvValidateConsole(OUT PCONSOLE* Console, - IN HANDLE ConsoleHandle, - IN CONSOLE_STATE ExpectedState, - IN BOOLEAN LockConsole) -{ - BOOLEAN RetVal = FALSE; - PCONSOLE ValidatedConsole; - - BOOLEAN ValidHandle = ((HandleToULong(ConsoleHandle) & 0x3) == 0x3); - ULONG Index = HandleToULong(ConsoleHandle) >> 2; - - if (!ValidHandle) return FALSE; - - if (!Console) return FALSE; - *Console = NULL; - - /* - * Forbid creation or deletion of consoles when - * checking for the existence of a console. - */ - ConDrvLockConsoleListShared(); - - if (Index >= ConsoleListSize || - (ValidatedConsole = ConsoleList[Index]) == NULL) - { - /* Unlock the console list */ - ConDrvUnlockConsoleList(); - - return FALSE; - } - - ValidatedConsole = ConsoleList[Index]; - - /* Unlock the console list and return */ - ConDrvUnlockConsoleList(); - - RetVal = ConDrvValidateConsoleUnsafe(ValidatedConsole, - ExpectedState, - LockConsole); - if (RetVal) *Console = ValidatedConsole; - - return RetVal; -} - -NTSTATUS NTAPI -ConDrvGetConsole(OUT PCONSOLE* Console, - IN HANDLE ConsoleHandle, - IN BOOLEAN LockConsole) -{ - NTSTATUS Status = STATUS_INVALID_HANDLE; - PCONSOLE GrabConsole; - - if (Console == NULL) return STATUS_INVALID_PARAMETER; - *Console = NULL; - - if (ConDrvValidateConsole(&GrabConsole, - ConsoleHandle, - CONSOLE_RUNNING, - LockConsole)) - { - InterlockedIncrement(&GrabConsole->ReferenceCount); - *Console = GrabConsole; - Status = STATUS_SUCCESS; - } - - return Status; -} - -VOID NTAPI -ConDrvReleaseConsole(IN PCONSOLE Console, - IN BOOLEAN WasConsoleLocked) -{ - LONG RefCount = 0; - - if (!Console) return; - // if (Console->ReferenceCount == 0) return; // This shouldn't happen - ASSERT(Console->ReferenceCount > 0); - - /* The console must be locked */ - // ASSERT(Console_locked); - - /* - * Decrement the reference count. Save the new value too, - * because Console->ReferenceCount might be modified after - * the console gets unlocked but before we check whether we - * can destroy it. - */ - RefCount = _InterlockedDecrement(&Console->ReferenceCount); - - /* Unlock the console if needed */ - if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock); - - /* Delete the console if needed */ - if (RefCount <= 0) ConDrvDeleteConsole(Console); -} - /* CONSOLE INITIALIZATION FUNCTIONS *******************************************/ @@ -432,93 +176,44 @@ ConDrvInitConsoleSupport(VOID) DPRINT("CONSRV: ConDrvInitConsoleSupport()\n"); /* Initialize the console list and its lock */ - ConsoleListSize = 0; - ConsoleList = NULL; + InitializeListHead(&ConsoleList); RtlInitializeResource(&ListLock); /* Should call LoadKeyboardLayout */ } +/* For resetting the terminal - defined in dummyterm.c */ +VOID ResetTerminal(IN PCONSOLE Console); + NTSTATUS NTAPI -ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, - OUT PCONSOLE* NewConsole, - IN PCONSOLE_INFO ConsoleInfo, - IN ULONG ConsoleLeaderProcessId) +ConDrvInitConsole(OUT PCONSOLE* NewConsole, + IN PCONSOLE_INFO ConsoleInfo) { NTSTATUS Status; SECURITY_ATTRIBUTES SecurityAttributes; // CONSOLE_INFO CapturedConsoleInfo; TEXTMODE_BUFFER_INFO ScreenBufferInfo; - HANDLE ConsoleHandle; PCONSOLE Console; PCONSOLE_SCREEN_BUFFER NewBuffer; - // WCHAR DefaultTitle[128]; +#if 0 + WCHAR DefaultTitle[128]; +#endif - if (NewConsoleHandle == NULL || NewConsole == NULL || ConsoleInfo == NULL) + if (NewConsole == NULL || ConsoleInfo == NULL) return STATUS_INVALID_PARAMETER; - *NewConsoleHandle = NULL; *NewConsole = NULL; /* - * Allocate a console structure + * Allocate a new console */ - Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(CONSOLE)); + Console = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Console)); if (NULL == Console) { DPRINT1("Not enough memory for console creation.\n"); return STATUS_NO_MEMORY; } - /* - * Load the console settings - */ - - /* 1. Load the default settings */ - // ConSrvGetDefaultSettings(ConsoleInfo, ProcessId); - - // /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */ - // Length = min(wcslen(ConsoleStartInfo->ConsoleTitle), - // sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1); - // wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length); - // ConsoleInfo.ConsoleTitle[Length] = L'\0'; - - /* - * 4. Load the remaining console settings via the registry. - */ -#if 0 - if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) - { - /* - * Either we weren't created by an app launched via a shell-link, - * or we failed to load shell-link console properties. - * Therefore, load the console infos for the application from the registry. - */ - ConSrvReadUserSettings(ConsoleInfo, ProcessId); - - /* - * Now, update them with the properties the user might gave to us - * via the STARTUPINFO structure before calling CreateProcess - * (and which was transmitted via the ConsoleStartInfo structure). - * We therefore overwrite the values read in the registry. - */ - if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE) - { - ConsoleInfo->ScreenAttrib = (USHORT)ConsoleStartInfo->FillAttribute; - } - if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS) - { - ConsoleInfo->ScreenBufferSize = ConsoleStartInfo->ScreenBufferSize; - } - if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE) - { - // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize; - ConsoleInfo->ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx; - ConsoleInfo->ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy; - } - } -#endif - /* * Fix the screen buffer size if needed. The rule is: * ScreenBufferSize >= ConsoleSize @@ -534,16 +229,13 @@ ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, Console->State = CONSOLE_INITIALIZING; Console->ReferenceCount = 0; InitializeCriticalSection(&Console->Lock); - InitializeListHead(&Console->ProcessList); - Console->NotifiedLastCloseProcess = NULL; - Console->NotifyLastClose = FALSE; - /* Initialize the frontend interface */ - ResetFrontEnd(Console); + /* Initialize the terminal interface */ + ResetTerminal(Console); memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(ConsoleInfo->Colors)); Console->ConsoleSize = ConsoleInfo->ConsoleSize; - Console->FixedSize = FALSE; // Value by default; is reseted by the front-ends if needed. + Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed. /* * Initialize the input buffer @@ -563,20 +255,18 @@ ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, Console->InputBuffer.InputBufferSize = 0; // FIXME! InitializeListHead(&Console->InputBuffer.InputEvents); - InitializeListHead(&Console->InputBuffer.ReadWaitQueue); Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT; - Console->QuickEdit = ConsoleInfo->QuickEdit; Console->InsertMode = ConsoleInfo->InsertMode; Console->LineBuffer = NULL; - Console->LineMaxSize = Console->LineSize = Console->LinePos = 0; + Console->LinePos = Console->LineMaxSize = Console->LineSize = 0; Console->LineComplete = Console->LineUpPressed = FALSE; Console->LineInsertToggle = Console->InsertMode; // LineWakeupMask /* Set-up the code page */ - Console->CodePage = Console->OutputCodePage = ConsoleInfo->CodePage; + Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage; /* Initialize a new text-mode screen buffer with default settings */ ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize; @@ -600,44 +290,34 @@ ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, } /* Make the new screen buffer active */ Console->ActiveBuffer = NewBuffer; - InitializeListHead(&Console->WriteWaitQueue); - Console->PauseFlags = 0; Console->UnpauseEvent = NULL; - /* - * Initialize the alias and history buffers - */ - Console->Aliases = NULL; - InitializeListHead(&Console->HistoryBuffers); - Console->HistoryBufferSize = ConsoleInfo->HistoryBufferSize; - Console->NumberOfHistoryBuffers = ConsoleInfo->NumberOfHistoryBuffers; - Console->HistoryNoDup = ConsoleInfo->HistoryNoDup; - /* Initialize the console title */ ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle); - // if (ConsoleInfo.ConsoleTitle[0] == L'\0') - // { - // if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0]))) - // { - // ConsoleCreateUnicodeString(&Console->Title, DefaultTitle); - // } - // else - // { - // ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console"); - // } - // } - // else - // { +#if 0 + if (ConsoleInfo.ConsoleTitle[0] == L'\0') + { + if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0]))) + { + ConsoleCreateUnicodeString(&Console->Title, DefaultTitle); + } + else + { + ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console"); + } + } + else + { +#endif ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle); - // } - - /* Lock the console until its initialization is finished */ - // EnterCriticalSection(&Console->Lock); +#if 0 + } +#endif DPRINT("Console initialized\n"); /* All went right, so add the console to the list */ - Status = InsertConsole(&ConsoleHandle, Console); + Status = InsertConsole(Console); if (!NT_SUCCESS(Status)) { /* Fail */ @@ -649,73 +329,69 @@ ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, DPRINT("Change state\n"); Console->State = CONSOLE_RUNNING; - /* Unlock the console */ - // LeaveCriticalSection(&Console->Lock); - /* Return the newly created console to the caller and a success code too */ - *NewConsoleHandle = ConsoleHandle; - *NewConsole = Console; + *NewConsole = Console; return STATUS_SUCCESS; } NTSTATUS NTAPI -ConDrvRegisterFrontEnd(IN PCONSOLE Console, - IN PFRONTEND FrontEnd) +ConDrvRegisterTerminal(IN PCONSOLE Console, + IN PTERMINAL Terminal) { NTSTATUS Status; - if (Console == NULL || FrontEnd == NULL) + if (Console == NULL || Terminal == NULL) return STATUS_INVALID_PARAMETER; /* FIXME: Lock the console before ?? */ /* - * Attach the frontend to the console. Use now the TermIFace of the console, - * and not the user-defined temporary FrontEnd pointer. + * Attach the terminal to the console. Use now the TermIFace of the console, + * and not the user-defined temporary Terminal pointer. */ - Console->TermIFace = *FrontEnd; + Console->TermIFace = *Terminal; Console->TermIFace.Console = Console; - /* Initialize the frontend AFTER having attached it to the console */ - DPRINT("Finish initialization of frontend\n"); - Status = Console->TermIFace.Vtbl->InitFrontEnd(&Console->TermIFace, Console); + /* Initialize the terminal AFTER having attached it to the console */ + DPRINT("Finish initialization of terminal\n"); + Status = Console->TermIFace.Vtbl->InitTerminal(&Console->TermIFace, Console); if (!NT_SUCCESS(Status)) { - DPRINT1("FrontEnd initialization failed, Status = 0x%08lx\n", Status); + DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status); - /* We failed, detach the frontend from the console */ - FrontEnd->Console = NULL; // For the caller - ResetFrontEnd(Console); + /* We failed, detach the terminal from the console */ + Terminal->Console = NULL; // For the caller + ResetTerminal(Console); return Status; } /* Copy buffer contents to screen */ - // FrontEnd.Draw(); + // Terminal.Draw(); // ConioDrawConsole(Console); DPRINT("Console drawn\n"); - DPRINT("Terminal FrontEnd initialization done\n"); + DPRINT("Terminal initialization done\n"); return STATUS_SUCCESS; } NTSTATUS NTAPI -ConDrvDeregisterFrontEnd(IN PCONSOLE Console) +ConDrvDeregisterTerminal(IN PCONSOLE Console) { if (Console == NULL) return STATUS_INVALID_PARAMETER; /* FIXME: Lock the console before ?? */ - /* Deinitialize the frontend BEFORE detaching it from the console */ - Console->TermIFace.Vtbl->DeinitFrontEnd(&Console->TermIFace/*, Console*/); + /* Deinitialize the terminal BEFORE detaching it from the console */ + Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/); /* - * Detach the frontend from the console: - * reinitialize the frontend interface. + * Detach the terminal from the console: + * reinitialize the terminal interface. */ - ResetFrontEnd(Console); + ResetTerminal(Console); - DPRINT("Terminal FrontEnd unregistered\n"); + DPRINT("Terminal unregistered\n"); return STATUS_SUCCESS; } @@ -752,7 +428,7 @@ ConDrvDeleteConsole(IN PCONSOLE Console) /* * Allow other threads to finish their job: basically, unlock * all other calls to EnterCriticalSection(&Console->Lock); by - * ConDrvValidateConsole(Unsafe) functions so that they just see + * ConDrvValidateConsoleUnsafe functions so that they just see * that we are not in CONSOLE_RUNNING state anymore, or unlock * other concurrent calls to ConDrvDeleteConsole so that they * can see that we are in fact already deleting the console. @@ -764,7 +440,7 @@ ConDrvDeleteConsole(IN PCONSOLE Console) /* Cleanup the UI-oriented part */ DPRINT("Deregister console\n"); - ConDrvDeregisterFrontEnd(Console); + ConDrvDeregisterTerminal(Console); DPRINT("Console deregistered\n"); /*** @@ -788,16 +464,13 @@ ConDrvDeleteConsole(IN PCONSOLE Console) Console->ReferenceCount = 0; /* Remove the console from the list */ - RemoveConsoleByPointer(Console); + RemoveConsole(Console); /* Discard all entries in the input event queue */ PurgeInputBuffer(Console); - if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer); - IntDeleteAllAliases(Console); - HistoryDeleteBuffers(Console); - + /* Delete the last screen buffer */ ConioDeleteScreenBuffer(Console->ActiveBuffer); Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) @@ -983,7 +656,7 @@ ConDrvGetConsoleTitle(IN PCONSOLE Console, if (*BufLength >= sizeof(CHAR)) { Length = min(*BufLength - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR)); - Length = WideCharToMultiByte(Console->CodePage, 0, + Length = WideCharToMultiByte(Console->InputCodePage, 0, Console->Title.Buffer, Length, TitleBuffer, Length, NULL, NULL); @@ -1019,7 +692,7 @@ ConDrvSetConsoleTitle(IN PCONSOLE Console, else { /* Use the console input CP for the conversion */ - Length = MultiByteToWideChar(Console->CodePage, 0, + Length = MultiByteToWideChar(Console->InputCodePage, 0, TitleBuffer, BufLength, NULL, 0); /* The returned Length was in number of wchars, convert it in bytes */ @@ -1044,7 +717,7 @@ ConDrvSetConsoleTitle(IN PCONSOLE Console, } else { - MultiByteToWideChar(Console->CodePage, 0, + MultiByteToWideChar(Console->InputCodePage, 0, TitleBuffer, BufLength, Console->Title.Buffer, Console->Title.Length / sizeof(WCHAR)); @@ -1065,7 +738,7 @@ ConDrvGetConsoleCP(IN PCONSOLE Console, if (Console == NULL || CodePage == NULL) return STATUS_INVALID_PARAMETER; - *CodePage = (OutputCP ? Console->OutputCodePage : Console->CodePage); + *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage); return STATUS_SUCCESS; } @@ -1081,86 +754,9 @@ ConDrvSetConsoleCP(IN PCONSOLE Console, if (OutputCP) Console->OutputCodePage = CodePage; else - Console->CodePage = CodePage; + Console->InputCodePage = CodePage; return STATUS_SUCCESS; } -PCONSOLE_PROCESS_DATA NTAPI -ConDrvGetConsoleLeaderProcess(IN PCONSOLE Console) -{ - if (Console == NULL) return NULL; - - return CONTAINING_RECORD(Console->ProcessList.Blink, - CONSOLE_PROCESS_DATA, - ConsoleLink); -} - -NTSTATUS NTAPI -ConDrvGetConsoleProcessList(IN PCONSOLE Console, - IN OUT PULONG ProcessIdsList, - IN ULONG MaxIdListItems, - OUT PULONG ProcessIdsTotal) -{ - PCONSOLE_PROCESS_DATA current; - PLIST_ENTRY current_entry; - - if (Console == NULL || ProcessIdsList == NULL || ProcessIdsTotal == NULL) - return STATUS_INVALID_PARAMETER; - - *ProcessIdsTotal = 0; - - for (current_entry = Console->ProcessList.Flink; - current_entry != &Console->ProcessList; - current_entry = current_entry->Flink) - { - current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink); - if (++(*ProcessIdsTotal) <= MaxIdListItems) - { - *ProcessIdsList++ = HandleToUlong(current->Process->ClientId.UniqueProcess); - } - } - - return STATUS_SUCCESS; -} - -// ConDrvGenerateConsoleCtrlEvent -NTSTATUS NTAPI -ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console, - IN ULONG ProcessGroupId, - IN ULONG CtrlEvent) -{ - NTSTATUS Status = STATUS_SUCCESS; - PLIST_ENTRY current_entry; - PCONSOLE_PROCESS_DATA current; - - /* If the console is already being destroyed, just return */ - if (!ConDrvValidateConsoleState(Console, CONSOLE_RUNNING)) - return STATUS_UNSUCCESSFUL; - - /* - * Loop through the process list, from the most recent process - * (the active one) to the oldest one (the first created, i.e. - * the console leader process), and for each, send an event - * (new processes are inserted at the head of the console process list). - */ - current_entry = Console->ProcessList.Flink; - while (current_entry != &Console->ProcessList) - { - current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink); - current_entry = current_entry->Flink; - - /* - * Only processes belonging to the same process group are signaled. - * If the process group ID is zero, then all the processes are signaled. - */ - if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId) - { - Status = ConDrvConsoleCtrlEvent(CtrlEvent, current); - } - } - - return Status; -} - /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/dummyfrontend.c b/reactos/win32ss/user/winsrv/consrv/condrv/dummyfrontend.c deleted file mode 100644 index c96cfe579ff..00000000000 --- a/reactos/win32ss/user/winsrv/consrv/condrv/dummyfrontend.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Console Server DLL - * FILE: win32ss/user/winsrv/consrv/condrv/dummyfrontend.c - * PURPOSE: Dummy Terminal Front-End used when no frontend - * is attached to the specified console. - * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) - */ - -/* INCLUDES *******************************************************************/ - -#include - -/* DUMMY FRONTEND INTERFACE ***************************************************/ - -static NTSTATUS NTAPI -DummyInitFrontEnd(IN OUT PFRONTEND This, - IN PCONSOLE Console) -{ - /* Load some settings ?? */ - return STATUS_SUCCESS; -} - -static VOID NTAPI -DummyDeinitFrontEnd(IN OUT PFRONTEND This) -{ - /* Free some settings ?? */ -} - -static VOID NTAPI -DummyDrawRegion(IN OUT PFRONTEND This, - SMALL_RECT* Region) -{ -} - -static VOID NTAPI -DummyWriteStream(IN OUT PFRONTEND This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length) -{ -} - -static BOOL NTAPI -DummySetCursorInfo(IN OUT PFRONTEND This, - PCONSOLE_SCREEN_BUFFER Buff) -{ - return TRUE; -} - -static BOOL NTAPI -DummySetScreenInfo(IN OUT PFRONTEND This, - PCONSOLE_SCREEN_BUFFER Buff, - SHORT OldCursorX, - SHORT OldCursorY) -{ - return TRUE; -} - -static VOID NTAPI -DummyResizeTerminal(IN OUT PFRONTEND This) -{ -} - -static VOID NTAPI -DummySetActiveScreenBuffer(IN OUT PFRONTEND This) -{ -} - -static VOID NTAPI -DummyReleaseScreenBuffer(IN OUT PFRONTEND This, - IN PCONSOLE_SCREEN_BUFFER ScreenBuffer) -{ -} - -static BOOL NTAPI -DummyProcessKeyCallback(IN OUT PFRONTEND This, - MSG* msg, - BYTE KeyStateMenu, - DWORD ShiftState, - UINT VirtualKeyCode, - BOOL Down) -{ - return FALSE; -} - -static VOID NTAPI -DummyRefreshInternalInfo(IN OUT PFRONTEND This) -{ -} - -static VOID NTAPI -DummyChangeTitle(IN OUT PFRONTEND This) -{ -} - -static BOOL NTAPI -DummyChangeIcon(IN OUT PFRONTEND This, - HICON IconHandle) -{ - return TRUE; -} - -static HWND NTAPI -DummyGetConsoleWindowHandle(IN OUT PFRONTEND This) -{ - return NULL; -} - -static VOID NTAPI -DummyGetLargestConsoleWindowSize(IN OUT PFRONTEND This, - PCOORD pSize) -{ -} - -static BOOL NTAPI -DummyGetSelectionInfo(IN OUT PFRONTEND This, - PCONSOLE_SELECTION_INFO pSelectionInfo) -{ - return TRUE; -} - -static BOOL NTAPI -DummySetPalette(IN OUT PFRONTEND This, - HPALETTE PaletteHandle, - UINT PaletteUsage) -{ - return TRUE; -} - -static ULONG NTAPI -DummyGetDisplayMode(IN OUT PFRONTEND This) -{ - return 0; -} - -static BOOL NTAPI -DummySetDisplayMode(IN OUT PFRONTEND This, - ULONG NewMode) -{ - return TRUE; -} - -static INT NTAPI -DummyShowMouseCursor(IN OUT PFRONTEND This, - BOOL Show) -{ - return 0; -} - -static BOOL NTAPI -DummySetMouseCursor(IN OUT PFRONTEND This, - HCURSOR CursorHandle) -{ - return TRUE; -} - -static HMENU NTAPI -DummyMenuControl(IN OUT PFRONTEND This, - UINT CmdIdLow, - UINT CmdIdHigh) -{ - return NULL; -} - -static BOOL NTAPI -DummySetMenuClose(IN OUT PFRONTEND This, - BOOL Enable) -{ - return TRUE; -} - -static FRONTEND_VTBL DummyVtbl = -{ - DummyInitFrontEnd, - DummyDeinitFrontEnd, - DummyDrawRegion, - DummyWriteStream, - DummySetCursorInfo, - DummySetScreenInfo, - DummyResizeTerminal, - DummySetActiveScreenBuffer, - DummyReleaseScreenBuffer, - DummyProcessKeyCallback, - DummyRefreshInternalInfo, - DummyChangeTitle, - DummyChangeIcon, - DummyGetConsoleWindowHandle, - DummyGetLargestConsoleWindowSize, - DummyGetSelectionInfo, - DummySetPalette, - DummyGetDisplayMode, - DummySetDisplayMode, - DummyShowMouseCursor, - DummySetMouseCursor, - DummyMenuControl, - DummySetMenuClose, -}; - -VOID -ResetFrontEnd(IN PCONSOLE Console) -{ - if (!Console) return; - - /* Reinitialize the frontend interface */ - RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace)); - Console->TermIFace.Vtbl = &DummyVtbl; -} - -/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c b/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c new file mode 100644 index 00000000000..3b38329cfcd --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c @@ -0,0 +1,140 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: condrv/dummyterm.c + * PURPOSE: Dummy Terminal used when no terminal + * is attached to the specified console. + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#include + +/* DUMMY TERMINAL INTERFACE ***************************************************/ + +static NTSTATUS NTAPI +DummyInitTerminal(IN OUT PTERMINAL This, + IN PCONSOLE Console) +{ + return STATUS_SUCCESS; +} + +static VOID NTAPI +DummyDeinitTerminal(IN OUT PTERMINAL This) +{ +} + +static VOID NTAPI +DummyDrawRegion(IN OUT PTERMINAL This, + SMALL_RECT* Region) +{ +} + +static VOID NTAPI +DummyWriteStream(IN OUT PTERMINAL This, + SMALL_RECT* Region, + SHORT CursorStartX, + SHORT CursorStartY, + UINT ScrolledLines, + PWCHAR Buffer, + UINT Length) +{ +} + +static BOOL NTAPI +DummySetCursorInfo(IN OUT PTERMINAL This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer) +{ + return TRUE; +} + +static BOOL NTAPI +DummySetScreenInfo(IN OUT PTERMINAL This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer, + SHORT OldCursorX, + SHORT OldCursorY) +{ + return TRUE; +} + +static VOID NTAPI +DummyResizeTerminal(IN OUT PTERMINAL This) +{ +} + +static VOID NTAPI +DummySetActiveScreenBuffer(IN OUT PTERMINAL This) +{ +} + +static VOID NTAPI +DummyReleaseScreenBuffer(IN OUT PTERMINAL This, + IN PCONSOLE_SCREEN_BUFFER ScreenBuffer) +{ +} + +static VOID NTAPI +DummyChangeTitle(IN OUT PTERMINAL This) +{ +} + +static VOID NTAPI +DummyGetLargestConsoleWindowSize(IN OUT PTERMINAL This, + PCOORD pSize) +{ +} + +/* +static BOOL NTAPI +DummyGetSelectionInfo(IN OUT PTERMINAL This, + PCONSOLE_SELECTION_INFO pSelectionInfo) +{ + return TRUE; +} +*/ + +static BOOL NTAPI +DummySetPalette(IN OUT PTERMINAL This, + HPALETTE PaletteHandle, + UINT PaletteUsage) +{ + return TRUE; +} + +static INT NTAPI +DummyShowMouseCursor(IN OUT PTERMINAL This, + BOOL Show) +{ + return 0; +} + +static TERMINAL_VTBL DummyVtbl = +{ + DummyInitTerminal, + DummyDeinitTerminal, + DummyDrawRegion, + DummyWriteStream, + DummySetCursorInfo, + DummySetScreenInfo, + DummyResizeTerminal, + DummySetActiveScreenBuffer, + DummyReleaseScreenBuffer, + DummyChangeTitle, + DummyGetLargestConsoleWindowSize, + // DummyGetSelectionInfo, + DummySetPalette, + DummyShowMouseCursor, +}; + +VOID +ResetTerminal(IN PCONSOLE Console) +{ + if (!Console) return; + + /* Reinitialize the terminal interface */ + RtlZeroMemory(&Console->TermIFace, sizeof(Console->TermIFace)); + Console->TermIFace.Vtbl = &DummyVtbl; +} + +/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/graphics.c b/reactos/win32ss/user/winsrv/consrv/condrv/graphics.c index 3d2805b558f..fbb1491ba65 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/graphics.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/graphics.c @@ -34,6 +34,7 @@ static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl = NTSTATUS CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, + IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl, IN SIZE_T Size); VOID CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer); @@ -58,10 +59,10 @@ GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer, Console, + &GraphicsVtbl, sizeof(GRAPHICS_SCREEN_BUFFER)); if (!NT_SUCCESS(Status)) return Status; NewBuffer->Header.Type = GRAPHICS_BUFFER; - NewBuffer->Vtbl = &GraphicsVtbl; /* * Remember the handle to the process so that we can close or unmap diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/text.c b/reactos/win32ss/user/winsrv/consrv/condrv/text.c index d44c9b39786..96e30035931 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/text.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/text.c @@ -33,13 +33,14 @@ static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl = }; -static VOID FASTCALL +static VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff); NTSTATUS CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, + IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl, IN SIZE_T Size); VOID CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer); @@ -60,10 +61,10 @@ TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer, Console, + &TextVtbl, sizeof(TEXTMODE_SCREEN_BUFFER)); if (!NT_SUCCESS(Status)) return Status; NewBuffer->Header.Type = TEXTMODE_BUFFER; - NewBuffer->Vtbl = &TextVtbl; NewBuffer->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, TextModeInfo->ScreenBufferSize.X * @@ -126,7 +127,7 @@ ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y) return &Buff->Buffer[((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X]; } -static VOID FASTCALL +static VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff) { PCHAR_INFO Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y); @@ -140,66 +141,7 @@ ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff) } } -static __inline BOOLEAN -ConioGetIntersection(OUT PSMALL_RECT Intersection, - IN PSMALL_RECT Rect1, - IN PSMALL_RECT Rect2) -{ - if ( ConioIsRectEmpty(Rect1) || - ConioIsRectEmpty(Rect2) || - (Rect1->Top > Rect2->Bottom) || - (Rect1->Left > Rect2->Right) || - (Rect1->Bottom < Rect2->Top) || - (Rect1->Right < Rect2->Left) ) - { - /* The rectangles do not intersect */ - ConioInitRect(Intersection, 0, -1, 0, -1); - return FALSE; - } - - ConioInitRect(Intersection, - max(Rect1->Top , Rect2->Top ), - max(Rect1->Left , Rect2->Left ), - min(Rect1->Bottom, Rect2->Bottom), - min(Rect1->Right , Rect2->Right )); - - return TRUE; -} - -static __inline BOOLEAN -ConioGetUnion(OUT PSMALL_RECT Union, - IN PSMALL_RECT Rect1, - IN PSMALL_RECT Rect2) -{ - if (ConioIsRectEmpty(Rect1)) - { - if (ConioIsRectEmpty(Rect2)) - { - ConioInitRect(Union, 0, -1, 0, -1); - return FALSE; - } - else - { - *Union = *Rect2; - } - } - else if (ConioIsRectEmpty(Rect2)) - { - *Union = *Rect1; - } - else - { - ConioInitRect(Union, - min(Rect1->Top , Rect2->Top ), - min(Rect1->Left , Rect2->Left ), - max(Rect1->Bottom, Rect2->Bottom), - max(Rect1->Right , Rect2->Right )); - } - - return TRUE; -} - -static VOID FASTCALL +static VOID ConioComputeUpdateRect(IN PTEXTMODE_SCREEN_BUFFER Buff, IN OUT PSMALL_RECT UpdateRect, IN PCOORD Start, @@ -233,7 +175,7 @@ ConioComputeUpdateRect(IN PTEXTMODE_SCREEN_BUFFER Buff, * Move from one rectangle to another. We must be careful about the order that * this is done, to avoid overwriting parts of the source before they are moved. */ -static VOID FASTCALL +static VOID ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer, PSMALL_RECT SrcRegion, PSMALL_RECT DstRegion, @@ -293,16 +235,6 @@ ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer, } } -DWORD FASTCALL -ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale) -{ - DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; - /* If line input in progress, perhaps adjust for insert toggle */ - if (Console->LineBuffer && !Console->LineComplete && (Console->InsertMode ? !Console->LineInsertToggle : Console->LineInsertToggle)) - return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); - return Size; -} - NTSTATUS ConioResizeBuffer(PCONSOLE Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, @@ -422,7 +354,7 @@ ConioResizeBuffer(PCONSOLE Console, return STATUS_SUCCESS; } -static VOID FASTCALL +static VOID ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines) { /* If we hit bottom, slide the viewable screen */ @@ -669,21 +601,15 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion) { + SHORT X, Y; + SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; - SHORT SizeX, SizeY; SMALL_RECT CapturedReadRegion; - SMALL_RECT ScreenRect; - DWORD i; PCHAR_INFO Ptr; - LONG X, Y; - UINT CodePage; - if (Console == NULL || Buffer == NULL || CharInfo == NULL || - BufferSize == NULL || BufferCoord == NULL || ReadRegion == NULL) + if (Console == NULL || Buffer == NULL || CharInfo == NULL || ReadRegion == NULL) { return STATUS_INVALID_PARAMETER; } @@ -693,26 +619,24 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, CapturedReadRegion = *ReadRegion; - /* FIXME: Is this correct? */ - CodePage = Console->OutputCodePage; - - SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedReadRegion)); - SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedReadRegion)); - CapturedReadRegion.Right = CapturedReadRegion.Left + SizeX; - CapturedReadRegion.Bottom = CapturedReadRegion.Top + SizeY; - - ConioInitRect(&ScreenRect, 0, 0, Buffer->ScreenBufferSize.Y, Buffer->ScreenBufferSize.X); - if (!ConioGetIntersection(&CapturedReadRegion, &ScreenRect, &CapturedReadRegion)) + /* Make sure ReadRegion is inside the screen buffer */ + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + if (!ConioGetIntersection(&CapturedReadRegion, &ScreenBuffer, &CapturedReadRegion)) { + /* + * It is okay to have a ReadRegion completely outside + * the screen buffer. No data is read then. + */ return STATUS_SUCCESS; } - for (i = 0, Y = CapturedReadRegion.Top; Y < CapturedReadRegion.Bottom; ++i, ++Y) - { - CurCharInfo = CharInfo + (i * BufferSize->X); + CurCharInfo = CharInfo; + for (Y = CapturedReadRegion.Top; Y <= CapturedReadRegion.Bottom; ++Y) + { Ptr = ConioCoordToPointer(Buffer, CapturedReadRegion.Left, Y); - for (X = CapturedReadRegion.Left; X < CapturedReadRegion.Right; ++X) + for (X = CapturedReadRegion.Left; X <= CapturedReadRegion.Right; ++X) { if (Unicode) { @@ -721,7 +645,7 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, else { // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); - WideCharToMultiByte(CodePage, 0, &Ptr->Char.UnicodeChar, 1, + WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1, &CurCharInfo->Char.AsciiChar, 1, NULL, NULL); } CurCharInfo->Attributes = Ptr->Attributes; @@ -730,10 +654,7 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, } } - ReadRegion->Left = CapturedReadRegion.Left; - ReadRegion->Top = CapturedReadRegion.Top ; - ReadRegion->Right = CapturedReadRegion.Left + SizeX - 1; - ReadRegion->Bottom = CapturedReadRegion.Top + SizeY - 1; + *ReadRegion = CapturedReadRegion; return STATUS_SUCCESS; } @@ -743,18 +664,15 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion) { - SHORT i, X, Y, SizeX, SizeY; + SHORT X, Y; SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; SMALL_RECT CapturedWriteRegion; PCHAR_INFO Ptr; - if (Console == NULL || Buffer == NULL || CharInfo == NULL || - BufferSize == NULL || BufferCoord == NULL || WriteRegion == NULL) + if (Console == NULL || Buffer == NULL || CharInfo == NULL || WriteRegion == NULL) { return STATUS_INVALID_PARAMETER; } @@ -764,13 +682,9 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, CapturedWriteRegion = *WriteRegion; - SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedWriteRegion)); - SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedWriteRegion)); - CapturedWriteRegion.Right = CapturedWriteRegion.Left + SizeX - 1; - CapturedWriteRegion.Bottom = CapturedWriteRegion.Top + SizeY - 1; - /* Make sure WriteRegion is inside the screen buffer */ - ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion)) { /* @@ -780,12 +694,12 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, return STATUS_SUCCESS; } - for (i = 0, Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; i++, Y++) - { - CurCharInfo = CharInfo + (i + BufferCoord->Y) * BufferSize->X + BufferCoord->X; + CurCharInfo = CharInfo; + for (Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; ++Y) + { Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); - for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; X++) + for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X) { if (Unicode) { @@ -803,10 +717,7 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, TermDrawRegion(Console, &CapturedWriteRegion); - WriteRegion->Left = CapturedWriteRegion.Left; - WriteRegion->Top = CapturedWriteRegion.Top ; - WriteRegion->Right = CapturedWriteRegion.Left + SizeX - 1; - WriteRegion->Bottom = CapturedWriteRegion.Top + SizeY - 1; + *WriteRegion = CapturedWriteRegion; return STATUS_SUCCESS; } @@ -829,14 +740,10 @@ ConDrvWriteConsole(IN PCONSOLE Console, /* Validity checks */ ASSERT(Console == ScreenBuffer->Header.Console); - ASSERT( (StringBuffer != NULL && NumCharsToWrite >= 0) || - (StringBuffer == NULL && NumCharsToWrite == 0) ); + ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCharsToWrite == 0)); - // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) - if (Console->PauseFlags && Console->UnpauseEvent != NULL) - { - return STATUS_PENDING; - } + /* Stop here if the console is paused */ + if (Console->UnpauseEvent != NULL) return STATUS_PENDING; if (Unicode) { @@ -892,8 +799,8 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, OUT PVOID StringBuffer, IN ULONG NumCodesToRead, IN PCOORD ReadCoord, - OUT PCOORD EndCoord, - OUT PULONG CodesRead) + // OUT PCOORD EndCoord, + OUT PULONG NumCodesRead OPTIONAL) { SHORT Xpos, Ypos; PVOID ReadBuffer; @@ -901,29 +808,29 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, ULONG CodeSize; PCHAR_INFO Ptr; - if (Console == NULL || Buffer == NULL || - ReadCoord == NULL || EndCoord == NULL || CodesRead == NULL) + if (Console == NULL || Buffer == NULL || ReadCoord == NULL /* || EndCoord == NULL */) { return STATUS_INVALID_PARAMETER; } /* Validity checks */ ASSERT(Console == Buffer->Header.Console); - ASSERT( (StringBuffer != NULL && NumCodesToRead >= 0) || - (StringBuffer == NULL && NumCodesToRead == 0) ); + ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0)); + + if (NumCodesRead) *NumCodesRead = 0; switch (CodeType) { case CODE_ASCII: - CodeSize = sizeof(CHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); break; case CODE_UNICODE: - CodeSize = sizeof(WCHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); break; case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); break; default: @@ -984,25 +891,11 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, } } - // switch (CodeType) - // { - // case CODE_UNICODE: - // *(PWCHAR)ReadBuffer = 0; - // break; + // EndCoord->X = Xpos; + // EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y; - // case CODE_ASCII: - // *(PCHAR)ReadBuffer = 0; - // break; - - // case CODE_ATTRIBUTE: - // *(PWORD)ReadBuffer = 0; - // break; - // } - - EndCoord->X = Xpos; - EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y; - - *CodesRead = (ULONG)((ULONG_PTR)ReadBuffer - (ULONG_PTR)StringBuffer) / CodeSize; + if (NumCodesRead) + *NumCodesRead = (ULONG)((ULONG_PTR)ReadBuffer - (ULONG_PTR)StringBuffer) / CodeSize; // <= NumCodesToRead return STATUS_SUCCESS; @@ -1014,9 +907,9 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, - IN PCOORD WriteCoord /*, - OUT PCOORD EndCoord, - OUT PULONG CodesWritten */) + IN PCOORD WriteCoord, + // OUT PCOORD EndCoord, + OUT PULONG NumCodesWritten OPTIONAL) { NTSTATUS Status = STATUS_SUCCESS; PVOID WriteBuffer = NULL; @@ -1025,29 +918,29 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, ULONG CodeSize; PCHAR_INFO Ptr; - if (Console == NULL || Buffer == NULL || - WriteCoord == NULL /* || EndCoord == NULL || CodesWritten == NULL */) + if (Console == NULL || Buffer == NULL || WriteCoord == NULL /* || EndCoord == NULL */) { return STATUS_INVALID_PARAMETER; } /* Validity checks */ ASSERT(Console == Buffer->Header.Console); - ASSERT( (StringBuffer != NULL && NumCodesToWrite >= 0) || - (StringBuffer == NULL && NumCodesToWrite == 0) ); + ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0)); + + if (NumCodesWritten) *NumCodesWritten = 0; switch (CodeType) { case CODE_ASCII: - CodeSize = sizeof(CHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); break; case CODE_UNICODE: - CodeSize = sizeof(WCHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); break; case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); break; default: @@ -1073,6 +966,12 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, { Status = STATUS_NO_MEMORY; } + + // FIXME: Quick fix: fix the CodeType and CodeSize since the + // ASCII string was converted into UNICODE. + // A proper fix needs to be written. + CodeType = CODE_UNICODE; + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); } else { @@ -1132,7 +1031,7 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, Cleanup: if (tmpString) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString); - // CodesWritten = Written; + if (NumCodesWritten) *NumCodesWritten = NumCodesToWrite; // Written; return Status; } @@ -1140,16 +1039,15 @@ NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, - IN PVOID Code, + IN CODE_ELEMENT Code, IN ULONG NumCodesToWrite, - IN PCOORD WriteCoord /*, - OUT PULONG CodesWritten */) + IN PCOORD WriteCoord, + OUT PULONG NumCodesWritten OPTIONAL) { DWORD X, Y, Length; // , Written = 0; PCHAR_INFO Ptr; - if (Console == NULL || Buffer == NULL || Code == NULL || - WriteCoord == NULL /* || CodesWritten == NULL */) + if (Console == NULL || Buffer == NULL || WriteCoord == NULL) { return STATUS_INVALID_PARAMETER; } @@ -1157,29 +1055,15 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console, /* Validity check */ ASSERT(Console == Buffer->Header.Console); -#if 0 - switch (CodeType) - { - case CODE_ASCII: - /* On-place conversion from the ASCII char to the UNICODE char */ - ConsoleAnsiCharToUnicodeChar(Console, &Code->UnicodeChar, &Code->AsciiChar); - /* Fall through */ - case CODE_UNICODE: - Code = &Code->UnicodeChar; - break; + if (NumCodesWritten) *NumCodesWritten = 0; - case CODE_ATTRIBUTE: - Code = &Code->Attribute; - break; - } -#else if (CodeType == CODE_ASCII) { - /* On-place conversion from the ASCII char to the UNICODE char */ - // FIXME: What if Code points to an invalid memory zone ?? - ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)Code, (PCHAR)Code); + /* Conversion from the ASCII char to the UNICODE char */ + CODE_ELEMENT tmp; + ConsoleAnsiCharToUnicodeChar(Console, &tmp.UnicodeChar, &Code.AsciiChar); + Code = tmp; } -#endif X = WriteCoord->X; Y = (WriteCoord->Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; @@ -1196,11 +1080,11 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console, { case CODE_ASCII: case CODE_UNICODE: - Ptr->Char.UnicodeChar = *(PWCHAR)Code; + Ptr->Char.UnicodeChar = Code.UnicodeChar; break; case CODE_ATTRIBUTE: - Ptr->Attributes = *(PWORD)Code; + Ptr->Attributes = Code.Attribute; break; } // ++Ptr; @@ -1224,7 +1108,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console, TermDrawRegion(Console, &UpdateRect); } - // CodesWritten = Written; // NumCodesToWrite; + if (NumCodesWritten) *NumCodesWritten = NumCodesToWrite; // Written; return STATUS_SUCCESS; } @@ -1323,7 +1207,8 @@ ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, CapturedDestinationOrigin = *DestinationOrigin; /* Make sure the source rectangle is inside the screen buffer */ - ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, ScrollRectangle)) { return STATUS_SUCCESS; @@ -1359,7 +1244,11 @@ ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, CapturedDestinationOrigin.X + ConioRectWidth(&SrcRegion ) - 1); if (!Unicode) - ConsoleAnsiCharToUnicodeChar(Console, &FillChar.Char.UnicodeChar, &FillChar.Char.AsciiChar); + { + WCHAR tmp; + ConsoleAnsiCharToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar); + FillChar.Char.UnicodeChar = tmp; + } ConioMoveRegion(Buffer, &SrcRegion, &DstRegion, &CapturedClipRectangle, FillChar); diff --git a/reactos/win32ss/user/winsrv/consrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/coninput.c index 97e1ee560dc..738e819c93f 100644 --- a/reactos/win32ss/user/winsrv/consrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/coninput.c @@ -36,6 +36,88 @@ typedef struct _GET_INPUT_INFO /* PRIVATE FUNCTIONS **********************************************************/ +/* + * This pre-processing code MUST be IN consrv ONLY + */ +/* static */ ULONG +PreprocessInput(PCONSOLE Console, + PINPUT_RECORD InputEvent, + ULONG NumEventsToWrite) +{ + ULONG NumEvents; + + /* + * Loop each event, and for each, check for pause or unpause + * and perform adequate behaviour. + */ + for (NumEvents = NumEventsToWrite; NumEvents > 0; --NumEvents) + { + /* Check for pause or unpause */ + if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown) + { + WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode; + if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD)) + { + DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState; + if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT && + (vk == VK_PAUSE || + (vk == 'S' && (cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && + !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))))) + { + ConioPause(Console, PAUSED_FROM_KEYBOARD); + + /* Skip the event */ + RtlMoveMemory(InputEvent, + InputEvent + 1, + (NumEvents - 1) * sizeof(INPUT_RECORD)); + --NumEventsToWrite; + continue; + } + } + else + { + if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN && + vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL) + { + ConioUnpause(Console, PAUSED_FROM_KEYBOARD); + + /* Skip the event */ + RtlMoveMemory(InputEvent, + InputEvent + 1, + (NumEvents - 1) * sizeof(INPUT_RECORD)); + --NumEventsToWrite; + continue; + } + } + } + + /* Go to the next event */ + ++InputEvent; + } + + return NumEventsToWrite; +} + +/* + * This post-processing code MUST be IN consrv ONLY + */ +/* static */ VOID +PostprocessInput(PCONSOLE Console) +{ + CsrNotifyWait(&Console->ReadWaitQueue, + FALSE, + NULL, + NULL); + if (!IsListEmpty(&Console->ReadWaitQueue)) + { + CsrDereferenceWait(&Console->ReadWaitQueue); + } +} + + + + + static NTSTATUS WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, @@ -51,7 +133,7 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, RtlMoveMemory(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO)); - if (!CsrCreateWait(&InputInfo->InputBuffer->ReadWaitQueue, + if (!CsrCreateWait(&InputInfo->InputBuffer->Header.Console->ReadWaitQueue, WaitFunction, InputInfo->CallingThread, ApiMessage, @@ -133,6 +215,7 @@ Quit: NTSTATUS NTAPI ConDrvReadConsole(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ IN BOOLEAN Unicode, OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, @@ -148,20 +231,64 @@ ReadChars(IN PGET_INPUT_INFO InputInfo, PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer; CONSOLE_READCONSOLE_CONTROL ReadControl; + UNICODE_STRING ExeName; + + PVOID Buffer; + ULONG NrCharactersRead = 0; + ULONG CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); + + /* Compute the executable name, if needed */ + if (ReadConsoleRequest->InitialNumBytes == 0 && + ReadConsoleRequest->ExeLength <= sizeof(ReadConsoleRequest->StaticBuffer)) + { + ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength; + ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer; + } + else + { + ExeName.Length = ExeName.MaximumLength = 0; + ExeName.Buffer = NULL; + } + + /* Build the ReadControl structure */ ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL); - ReadControl.nInitialChars = ReadConsoleRequest->NrCharactersRead; + ReadControl.nInitialChars = ReadConsoleRequest->InitialNumBytes / CharSize; ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask; ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer)) + { + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer; + Buffer = ReadConsoleRequest->StaticBuffer; + } + else + { + Buffer = ReadConsoleRequest->Buffer; + } + + DPRINT1("Calling ConDrvReadConsole(%wZ)\n", &ExeName); Status = ConDrvReadConsole(InputBuffer->Header.Console, InputBuffer, + &ExeName, ReadConsoleRequest->Unicode, - ReadConsoleRequest->Buffer, + Buffer, &ReadControl, - ReadConsoleRequest->NrCharactersToRead, - &ReadConsoleRequest->NrCharactersRead); + ReadConsoleRequest->NumBytes / CharSize, // NrCharactersToRead + &NrCharactersRead); + DPRINT1("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n", + NrCharactersRead, Status); - ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState; + // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState; if (Status == STATUS_PENDING) { @@ -173,7 +300,13 @@ ReadChars(IN PGET_INPUT_INFO InputInfo, } else { - /* We read all what we wanted, we return the error code we were given */ + /* + * We read all what we wanted. Set the number of bytes read and + * return the error code we were given. + */ + ReadConsoleRequest->NumBytes = NrCharactersRead * CharSize; + ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState; + return Status; // return STATUS_SUCCESS; } @@ -260,17 +393,39 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, NTSTATUS Status; PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest; PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer; + ULONG NumEventsRead; - // GetInputRequest->InputsRead = 0; + PINPUT_RECORD InputRecord; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than five + * input records are read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) + { + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer; + InputRecord = GetInputRequest->RecordStaticBuffer; + } + else + { + InputRecord = GetInputRequest->RecordBufPtr; + } + + NumEventsRead = 0; Status = ConDrvGetConsoleInput(InputBuffer->Header.Console, InputBuffer, - (GetInputRequest->wFlags & CONSOLE_READ_KEEPEVENT) != 0, - (GetInputRequest->wFlags & CONSOLE_READ_CONTINUE ) == 0, + (GetInputRequest->Flags & CONSOLE_READ_KEEPEVENT) != 0, + (GetInputRequest->Flags & CONSOLE_READ_CONTINUE ) == 0, GetInputRequest->Unicode, - GetInputRequest->InputRecord, - GetInputRequest->Length, - &GetInputRequest->InputsRead); + InputRecord, + GetInputRequest->NumRecords, + &NumEventsRead); if (Status == STATUS_PENDING) { @@ -282,7 +437,12 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, } else { - /* We read all what we wanted, we return the error code we were given */ + /* + * We read all what we wanted. Set the number of events read and + * return the error code we were given. + */ + GetInputRequest->NumRecords = NumEventsRead; + return Status; // return STATUS_SUCCESS; } @@ -302,15 +462,32 @@ CSR_API(SrvReadConsole) DPRINT("SrvReadConsole\n"); - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ReadConsoleRequest->Buffer, - ReadConsoleRequest->BufferSize, - sizeof(BYTE))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadConsoleRequest->Buffer, + ReadConsoleRequest->CaptureBufferSize, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } } - if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead) + if (ReadConsoleRequest->InitialNumBytes > ReadConsoleRequest->NumBytes) { return STATUS_INVALID_PARAMETER; } @@ -318,9 +495,6 @@ CSR_API(SrvReadConsole) Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; - // This member is set by the caller (IntReadConsole in kernel32) - // ReadConsoleRequest->NrCharactersRead = 0; - InputInfo.CallingThread = CsrGetClientThread(); InputInfo.HandleEntry = HandleEntry; InputInfo.InputBuffer = InputBuffer; @@ -345,22 +519,37 @@ CSR_API(SrvGetConsoleInput) DPRINT("SrvGetConsoleInput\n"); - if (GetInputRequest->wFlags & ~(CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE)) + if (GetInputRequest->Flags & ~(CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE)) return STATUS_INVALID_PARAMETER; - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetInputRequest->InputRecord, - GetInputRequest->Length, - sizeof(INPUT_RECORD))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than five + * input records are read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetInputRequest->RecordBufPtr, + GetInputRequest->NumRecords, + sizeof(INPUT_RECORD))) + { + return STATUS_INVALID_PARAMETER; + } } Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; - GetInputRequest->InputsRead = 0; - InputInfo.CallingThread = CsrGetClientThread(); InputInfo.HandleEntry = HandleEntry; InputInfo.InputBuffer = InputBuffer; @@ -389,30 +578,56 @@ CSR_API(SrvWriteConsoleInput) PCONSOLE_INPUT_BUFFER InputBuffer; ULONG NumEventsWritten; + PINPUT_RECORD InputRecord; + DPRINT("SrvWriteConsoleInput\n"); - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&WriteInputRequest->InputRecord, - WriteInputRequest->Length, - sizeof(INPUT_RECORD))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than five + * input records are written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (WriteInputRequest->NumRecords <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer; + InputRecord = WriteInputRequest->RecordStaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&WriteInputRequest->RecordBufPtr, + WriteInputRequest->NumRecords, + sizeof(INPUT_RECORD))) + { + return STATUS_INVALID_PARAMETER; + } + + InputRecord = WriteInputRequest->RecordBufPtr; } Status = ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), WriteInputRequest->InputHandle, &InputBuffer, GENERIC_WRITE, TRUE); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + WriteInputRequest->NumRecords = 0; + return Status; + } NumEventsWritten = 0; Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console, InputBuffer, WriteInputRequest->Unicode, WriteInputRequest->AppendToEnd, - WriteInputRequest->InputRecord, - WriteInputRequest->Length, + InputRecord, + WriteInputRequest->NumRecords, &NumEventsWritten); - WriteInputRequest->Length = NumEventsWritten; + WriteInputRequest->NumRecords = NumEventsWritten; ConSrvReleaseInputBuffer(InputBuffer, TRUE); return Status; diff --git a/reactos/win32ss/user/winsrv/consrv/coninput.h b/reactos/win32ss/user/winsrv/consrv/coninput.h index 8d37087a556..7ab46946777 100644 --- a/reactos/win32ss/user/winsrv/consrv/coninput.h +++ b/reactos/win32ss/user/winsrv/consrv/coninput.h @@ -9,13 +9,4 @@ #pragma once -VOID FASTCALL PurgeInputBuffer(PCONSOLE Console); - -VOID NTAPI -ConDrvProcessKey(IN PCONSOLE Console, - IN BOOLEAN Down, - IN UINT VirtualKeyCode, - IN UINT VirtualScanCode, - IN WCHAR UnicodeChar, - IN ULONG ShiftState, - IN BYTE KeyStateCtrl); +VOID PurgeInputBuffer(PCONSOLE Console); diff --git a/reactos/win32ss/user/winsrv/consrv/conoutput.c b/reactos/win32ss/user/winsrv/consrv/conoutput.c index f5dac648a2c..833b3cdbb79 100644 --- a/reactos/win32ss/user/winsrv/consrv/conoutput.c +++ b/reactos/win32ss/user/winsrv/consrv/conoutput.c @@ -373,17 +373,45 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; PTEXTMODE_SCREEN_BUFFER ScreenBuffer; + PVOID Buffer; + ULONG NrCharactersWritten = 0; + ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); + Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &ScreenBuffer, GENERIC_WRITE, FALSE); if (!NT_SUCCESS(Status)) return Status; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (WriteConsoleRequest->UsingStaticBuffer && + WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer)) + { + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer; + Buffer = WriteConsoleRequest->StaticBuffer; + } + else + { + Buffer = WriteConsoleRequest->Buffer; + } + + DPRINT("Calling ConDrvWriteConsole\n"); Status = ConDrvWriteConsole(ScreenBuffer->Header.Console, ScreenBuffer, WriteConsoleRequest->Unicode, - WriteConsoleRequest->Buffer, - WriteConsoleRequest->NrCharactersToWrite, - &WriteConsoleRequest->NrCharactersWritten); + Buffer, + WriteConsoleRequest->NumBytes / CharSize, // NrCharactersToWrite + &NrCharactersWritten); + DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n", + NrCharactersWritten, Status); if (Status == STATUS_PENDING) { @@ -404,6 +432,11 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, /* Wait until we un-pause the console */ // Status = STATUS_PENDING; } + else + { + /* We read all what we wanted. Set the number of bytes written. */ + WriteConsoleRequest->NumBytes = NrCharactersWritten * CharSize; + } Quit: ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE); @@ -418,8 +451,6 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion); CSR_API(SrvReadConsoleOutput) { @@ -427,14 +458,40 @@ CSR_API(SrvReadConsoleOutput) PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; + ULONG NumCells; + PCHAR_INFO CharInfo; + DPRINT("SrvReadConsoleOutput\n"); - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ReadOutputRequest->CharInfo, - ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y, - sizeof(CHAR_INFO))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + NumCells = (ReadOutputRequest->ReadRegion.Right - ReadOutputRequest->ReadRegion.Left + 1) * + (ReadOutputRequest->ReadRegion.Bottom - ReadOutputRequest->ReadRegion.Top + 1); + + if (NumCells <= 1) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer; + CharInfo = &ReadOutputRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadOutputRequest->CharInfo, + NumCells, + sizeof(CHAR_INFO))) + { + return STATUS_INVALID_PARAMETER; + } + + CharInfo = ReadOutputRequest->CharInfo; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), @@ -445,9 +502,7 @@ CSR_API(SrvReadConsoleOutput) Status = ConDrvReadConsoleOutput(Buffer->Header.Console, Buffer, ReadOutputRequest->Unicode, - ReadOutputRequest->CharInfo, - &ReadOutputRequest->BufferSize, - &ReadOutputRequest->BufferCoord, + CharInfo, &ReadOutputRequest->ReadRegion); ConSrvReleaseScreenBuffer(Buffer, TRUE); @@ -459,8 +514,6 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion); CSR_API(SrvWriteConsoleOutput) { @@ -468,14 +521,40 @@ CSR_API(SrvWriteConsoleOutput) PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; + ULONG NumCells; + PCHAR_INFO CharInfo; + DPRINT("SrvWriteConsoleOutput\n"); - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&WriteOutputRequest->CharInfo, - WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y, - sizeof(CHAR_INFO))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + NumCells = (WriteOutputRequest->WriteRegion.Right - WriteOutputRequest->WriteRegion.Left + 1) * + (WriteOutputRequest->WriteRegion.Bottom - WriteOutputRequest->WriteRegion.Top + 1); + + if (NumCells <= 1) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer; + CharInfo = &WriteOutputRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&WriteOutputRequest->CharInfo, + NumCells, + sizeof(CHAR_INFO))) + { + return STATUS_INVALID_PARAMETER; + } + + CharInfo = WriteOutputRequest->CharInfo; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), @@ -486,9 +565,7 @@ CSR_API(SrvWriteConsoleOutput) Status = ConDrvWriteConsoleOutput(Buffer->Header.Console, Buffer, WriteOutputRequest->Unicode, - WriteOutputRequest->CharInfo, - &WriteOutputRequest->BufferSize, - &WriteOutputRequest->BufferCoord, + CharInfo, &WriteOutputRequest->WriteRegion); ConSrvReleaseScreenBuffer(Buffer, TRUE); @@ -502,12 +579,30 @@ CSR_API(SrvWriteConsole) DPRINT("SrvWriteConsole\n"); - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID)&WriteConsoleRequest->Buffer, - WriteConsoleRequest->BufferSize, - sizeof(BYTE))) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (WriteConsoleRequest->UsingStaticBuffer && + WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID)&WriteConsoleRequest->Buffer, + WriteConsoleRequest->NumBytes, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } } Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE); @@ -524,8 +619,8 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, OUT PVOID StringBuffer, IN ULONG NumCodesToRead, IN PCOORD ReadCoord, - OUT PCOORD EndCoord, - OUT PULONG CodesRead); + // OUT PCOORD EndCoord, + OUT PULONG NumCodesRead OPTIONAL); CSR_API(SrvReadConsoleOutputString) { NTSTATUS Status; @@ -533,47 +628,73 @@ CSR_API(SrvReadConsoleOutputString) PTEXTMODE_SCREEN_BUFFER Buffer; ULONG CodeSize; + PVOID pCode; + DPRINT("SrvReadConsoleOutputString\n"); switch (ReadOutputCodeRequest->CodeType) { case CODE_ASCII: - CodeSize = sizeof(CHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); break; case CODE_UNICODE: - CodeSize = sizeof(WCHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); break; case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); break; default: return STATUS_INVALID_PARAMETER; } - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ReadOutputCodeRequest->pCode.pCode, - ReadOutputCodeRequest->NumCodesToRead, - CodeSize)) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (ReadOutputCodeRequest->NumCodes * CodeSize <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer; + pCode = ReadOutputCodeRequest->CodeStaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadOutputCodeRequest->pCode, + ReadOutputCodeRequest->NumCodes, + CodeSize)) + { + return STATUS_INVALID_PARAMETER; + } + + pCode = ReadOutputCodeRequest->pCode; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputCodeRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + ReadOutputCodeRequest->NumCodes = 0; + return Status; + } Status = ConDrvReadConsoleOutputString(Buffer->Header.Console, Buffer, ReadOutputCodeRequest->CodeType, - ReadOutputCodeRequest->pCode.pCode, - ReadOutputCodeRequest->NumCodesToRead, - &ReadOutputCodeRequest->ReadCoord, - &ReadOutputCodeRequest->EndCoord, - &ReadOutputCodeRequest->CodesRead); + pCode, + ReadOutputCodeRequest->NumCodes, + &ReadOutputCodeRequest->Coord, + // &ReadOutputCodeRequest->EndCoord, + &ReadOutputCodeRequest->NumCodes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; @@ -585,9 +706,9 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, - IN PCOORD WriteCoord /*, - OUT PCOORD EndCoord, - OUT PULONG CodesWritten */); + IN PCOORD WriteCoord, + // OUT PCOORD EndCoord, + OUT PULONG NumCodesWritten OPTIONAL); CSR_API(SrvWriteConsoleOutputString) { NTSTATUS Status; @@ -595,49 +716,73 @@ CSR_API(SrvWriteConsoleOutputString) PTEXTMODE_SCREEN_BUFFER Buffer; ULONG CodeSize; + PVOID pCode; + DPRINT("SrvWriteConsoleOutputString\n"); switch (WriteOutputCodeRequest->CodeType) { case CODE_ASCII: - CodeSize = sizeof(CHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); break; case CODE_UNICODE: - CodeSize = sizeof(WCHAR); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); break; case CODE_ATTRIBUTE: - CodeSize = sizeof(WORD); + CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); break; default: return STATUS_INVALID_PARAMETER; } - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&WriteOutputCodeRequest->pCode.pCode, - WriteOutputCodeRequest->Length, - CodeSize)) + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than eighty + * bytes are written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + if (WriteOutputCodeRequest->NumCodes * CodeSize <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer)) { - return STATUS_INVALID_PARAMETER; + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer; + pCode = WriteOutputCodeRequest->CodeStaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&WriteOutputCodeRequest->pCode, + WriteOutputCodeRequest->NumCodes, + CodeSize)) + { + return STATUS_INVALID_PARAMETER; + } + + pCode = WriteOutputCodeRequest->pCode; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), WriteOutputCodeRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + WriteOutputCodeRequest->NumCodes = 0; + return Status; + } Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console, Buffer, WriteOutputCodeRequest->CodeType, - WriteOutputCodeRequest->pCode.pCode, - WriteOutputCodeRequest->Length, // NumCodesToWrite, - &WriteOutputCodeRequest->Coord /*, // WriteCoord, - &WriteOutputCodeRequest->EndCoord, - &WriteOutputCodeRequest->NrCharactersWritten */); - - // WriteOutputCodeRequest->NrCharactersWritten = Written; + pCode, + WriteOutputCodeRequest->NumCodes, + &WriteOutputCodeRequest->Coord, + // &WriteOutputCodeRequest->EndCoord, + &WriteOutputCodeRequest->NumCodes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; @@ -647,16 +792,16 @@ NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, - IN PVOID Code, + IN CODE_ELEMENT Code, IN ULONG NumCodesToWrite, - IN PCOORD WriteCoord /*, - OUT PULONG CodesWritten */); + IN PCOORD WriteCoord, + OUT PULONG NumCodesWritten OPTIONAL); CSR_API(SrvFillConsoleOutput) { NTSTATUS Status; PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; - USHORT CodeType = FillOutputRequest->CodeType; + CODE_TYPE CodeType = FillOutputRequest->CodeType; DPRINT("SrvFillConsoleOutput\n"); @@ -670,17 +815,19 @@ CSR_API(SrvFillConsoleOutput) Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + FillOutputRequest->NumCodes = 0; + return Status; + } Status = ConDrvFillConsoleOutput(Buffer->Header.Console, Buffer, CodeType, - &FillOutputRequest->Code, - FillOutputRequest->Length, // NumCodesToWrite, - &FillOutputRequest->Coord /*, // WriteCoord, - &FillOutputRequest->NrCharactersWritten */); - - // FillOutputRequest->NrCharactersWritten = Written; + FillOutputRequest->Code, + FillOutputRequest->NumCodes, + &FillOutputRequest->WriteCoord, + &FillOutputRequest->NumCodes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; diff --git a/reactos/win32ss/user/winsrv/consrv/conoutput.h b/reactos/win32ss/user/winsrv/consrv/conoutput.h index 29da4c4c699..802b8c4742d 100644 --- a/reactos/win32ss/user/winsrv/consrv/conoutput.h +++ b/reactos/win32ss/user/winsrv/consrv/conoutput.h @@ -33,12 +33,12 @@ #define ConSrvReleaseScreenBuffer(Buff, IsConsoleLocked) \ ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked)) -NTSTATUS FASTCALL ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer, +NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, IN ULONG BufferType, IN PVOID ScreenBufferInfo); VOID NTAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); -// VOID FASTCALL ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); +// VOID ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); PCONSOLE_SCREEN_BUFFER ConDrvGetActiveScreenBuffer(IN PCONSOLE Console); diff --git a/reactos/win32ss/user/winsrv/consrv/console.c b/reactos/win32ss/user/winsrv/consrv/console.c index 441e07d74de..b4f0d4ffd01 100644 --- a/reactos/win32ss/user/winsrv/consrv/console.c +++ b/reactos/win32ss/user/winsrv/consrv/console.c @@ -14,102 +14,217 @@ #include +#include #include "procinit.h" -#ifdef TUITERM_COMPILE -#include "frontends/tui/tuiterm.h" -#endif - #define NDEBUG #include +// FIXME: Add this prototype to winternl.h / rtlfuncs.h / ... +NTSTATUS NTAPI RtlGetLastNtStatus(VOID); + /* GLOBALS ********************************************************************/ -/***************/ -#ifdef TUITERM_COMPILE -NTSTATUS NTAPI -TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, - IN OUT PCONSOLE_INFO ConsoleInfo, - IN OUT PVOID ExtraConsoleInfo, - IN ULONG ProcessId); -NTSTATUS NTAPI -TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd); +static ULONG ConsoleListSize; +static PCONSOLE* ConsoleList; /* The list of the ConSrv consoles */ +static RTL_RESOURCE ListLock; + +#define ConSrvLockConsoleListExclusive() \ + RtlAcquireResourceExclusive(&ListLock, TRUE) + +#define ConSrvLockConsoleListShared() \ + RtlAcquireResourceShared(&ListLock, TRUE) + +#define ConSrvUnlockConsoleList() \ + RtlReleaseResource(&ListLock) + + +static NTSTATUS +InsertConsole(OUT PHANDLE Handle, + IN PCONSOLE Console) +{ +#define CONSOLE_HANDLES_INCREMENT 2 * 3 + + NTSTATUS Status = STATUS_SUCCESS; + ULONG i = 0; + PCONSOLE* Block; + + ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || + (ConsoleList != NULL && ConsoleListSize != 0) ); + + /* All went right, so add the console to the list */ + ConSrvLockConsoleListExclusive(); + DPRINT1("Insert in the list\n"); + + if (ConsoleList) + { + for (i = 0; i < ConsoleListSize; i++) + { + if (ConsoleList[i] == NULL) break; + } + } + + if (i >= ConsoleListSize) + { + DPRINT1("Creation of a new handles table\n"); + /* Allocate a new handles table */ + Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY, + (ConsoleListSize + + CONSOLE_HANDLES_INCREMENT) * sizeof(PCONSOLE)); + if (Block == NULL) + { + Status = STATUS_UNSUCCESSFUL; + goto Quit; + } + + /* If we previously had a handles table, free it and use the new one */ + if (ConsoleList) + { + /* Copy the handles from the old table to the new one */ + RtlCopyMemory(Block, + ConsoleList, + ConsoleListSize * sizeof(PCONSOLE)); + ConsoleFreeHeap(ConsoleList); + } + ConsoleList = Block; + ConsoleListSize += CONSOLE_HANDLES_INCREMENT; + } + + ConsoleList[i] = Console; + *Handle = ULongToHandle((i << 2) | 0x3); + +Quit: + /* Unlock the console list and return status */ + ConSrvUnlockConsoleList(); + return Status; +} + +/* Unused */ +#if 0 +static NTSTATUS +RemoveConsoleByHandle(IN HANDLE Handle) +{ + NTSTATUS Status = STATUS_SUCCESS; + PCONSOLE Console; + + BOOLEAN ValidHandle = ((HandleToULong(Handle) & 0x3) == 0x3); + ULONG Index = HandleToULong(Handle) >> 2; + + if (!ValidHandle) return STATUS_INVALID_HANDLE; + + ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || + (ConsoleList != NULL && ConsoleListSize != 0) ); + + /* Remove the console from the list */ + ConSrvLockConsoleListExclusive(); + + if (Index >= ConsoleListSize || + (Console = ConsoleList[Index]) == NULL) + { + Status = STATUS_INVALID_HANDLE; + goto Quit; + } + + ConsoleList[Index] = NULL; + +Quit: + /* Unlock the console list and return status */ + ConSrvUnlockConsoleList(); + return Status; +} #endif -NTSTATUS NTAPI -GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, - IN OUT PCONSOLE_INFO ConsoleInfo, - IN OUT PVOID ExtraConsoleInfo, - IN ULONG ProcessId); -NTSTATUS NTAPI -GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd); -/***************/ - -typedef -NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd, - IN OUT PCONSOLE_INFO ConsoleInfo, - IN OUT PVOID ExtraConsoleInfo, - IN ULONG ProcessId); - -typedef -NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd); - -/* - * If we are not in GUI-mode, start the text-mode terminal emulator. - * If we fail, try to start the GUI-mode terminal emulator. - * - * Try to open the GUI-mode terminal emulator. Two cases are possible: - * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case - * failed and we start GUI-mode terminal emulator. - * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case - * succeeded BUT we failed at starting text-mode terminal emulator. - * Then GuiMode was switched to TRUE in order to try to open the GUI-mode - * terminal emulator (Win32k will automatically switch to graphical mode, - * therefore no additional code is needed). - */ - -/* - * NOTE: Each entry of the table should be retrieved when loading a front-end - * (examples of the CSR servers which register some data for CSRSS). - */ -struct +static NTSTATUS +RemoveConsoleByPointer(IN PCONSOLE Console) { - CHAR FrontEndName[80]; - FRONTEND_LOAD FrontEndLoad; - FRONTEND_UNLOAD FrontEndUnload; -} FrontEndLoadingMethods[] = -{ -#ifdef TUITERM_COMPILE - {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd}, -#endif - {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd}, + ULONG i = 0; -// {"Not found", 0, NULL} -}; + if (!Console) return STATUS_INVALID_PARAMETER; + + ASSERT( (ConsoleList == NULL && ConsoleListSize == 0) || + (ConsoleList != NULL && ConsoleListSize != 0) ); + + /* Remove the console from the list */ + ConSrvLockConsoleListExclusive(); + + if (ConsoleList) + { + for (i = 0; i < ConsoleListSize; i++) + { + if (ConsoleList[i] == Console) ConsoleList[i] = NULL; + } + } + + /* Unlock the console list */ + ConSrvUnlockConsoleList(); + + return STATUS_SUCCESS; +} + +BOOLEAN NTAPI +ConSrvValidateConsole(OUT PCONSOLE* Console, + IN HANDLE ConsoleHandle, + IN CONSOLE_STATE ExpectedState, + IN BOOLEAN LockConsole) +{ + BOOLEAN RetVal = FALSE; + PCONSOLE ValidatedConsole; + + BOOLEAN ValidHandle = ((HandleToULong(ConsoleHandle) & 0x3) == 0x3); + ULONG Index = HandleToULong(ConsoleHandle) >> 2; + + if (!ValidHandle) return FALSE; + + if (!Console) return FALSE; + *Console = NULL; + + /* + * Forbid creation or deletion of consoles when + * checking for the existence of a console. + */ + ConSrvLockConsoleListShared(); + + if (Index >= ConsoleListSize || + (ValidatedConsole = ConsoleList[Index]) == NULL) + { + /* Unlock the console list */ + ConSrvUnlockConsoleList(); + + return FALSE; + } + + ValidatedConsole = ConsoleList[Index]; + + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); + + RetVal = ConDrvValidateConsoleUnsafe(ValidatedConsole, + ExpectedState, + LockConsole); + if (RetVal) *Console = ValidatedConsole; + + return RetVal; +} /* PRIVATE FUNCTIONS **********************************************************/ -#if 0000 -VOID FASTCALL +VOID ConioPause(PCONSOLE Console, UINT Flags) { Console->PauseFlags |= Flags; - if (!Console->UnpauseEvent) - Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + ConDrvPause(Console); } -VOID FASTCALL +VOID ConioUnpause(PCONSOLE Console, UINT Flags) { Console->PauseFlags &= ~Flags; // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0) - if (Console->PauseFlags == 0 && Console->UnpauseEvent) + if (Console->PauseFlags == 0) { - SetEvent(Console->UnpauseEvent); - CloseHandle(Console->UnpauseEvent); - Console->UnpauseEvent = NULL; + ConDrvUnpause(Console); CsrNotifyWait(&Console->WriteWaitQueue, TRUE, @@ -121,38 +236,87 @@ ConioUnpause(PCONSOLE Console, UINT Flags) } } } -#endif - -NTSTATUS FASTCALL -ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData, - PCONSOLE* Console, - BOOL LockConsole) +NTSTATUS +ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData, + OUT PCONSOLE* Console, + IN BOOLEAN LockConsole) { - NTSTATUS Status = STATUS_SUCCESS; - PCONSOLE ProcessConsole; + NTSTATUS Status = STATUS_INVALID_HANDLE; + PCONSOLE GrabConsole; + // if (Console == NULL) return STATUS_INVALID_PARAMETER; ASSERT(Console); *Console = NULL; // RtlEnterCriticalSection(&ProcessData->HandleTableLock); - Status = ConDrvGetConsole(&ProcessConsole, ProcessData->ConsoleHandle, LockConsole); - if (NT_SUCCESS(Status)) *Console = ProcessConsole; + if (ConSrvValidateConsole(&GrabConsole, + ProcessData->ConsoleHandle, + CONSOLE_RUNNING, + LockConsole)) + { + InterlockedIncrement(&GrabConsole->ReferenceCount); + *Console = GrabConsole; + Status = STATUS_SUCCESS; + } // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); return Status; } -VOID FASTCALL -ConSrvReleaseConsole(PCONSOLE Console, - BOOL WasConsoleLocked) +VOID +ConSrvReleaseConsole(IN PCONSOLE Console, + IN BOOLEAN WasConsoleLocked) { - /* Just call the driver */ - ConDrvReleaseConsole(Console, WasConsoleLocked); + LONG RefCount = 0; + + if (!Console) return; + // if (Console->ReferenceCount == 0) return; // This shouldn't happen + ASSERT(Console->ReferenceCount > 0); + + /* The console must be locked */ + // ASSERT(Console_locked); + + /* + * Decrement the reference count. Save the new value too, + * because Console->ReferenceCount might be modified after + * the console gets unlocked but before we check whether we + * can destroy it. + */ + RefCount = _InterlockedDecrement(&Console->ReferenceCount); + + /* Unlock the console if needed */ + if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock); + + /* Delete the console if needed */ + if (RefCount <= 0) ConSrvDeleteConsole(Console); } +/* CONSOLE INITIALIZATION FUNCTIONS *******************************************/ + +VOID NTAPI +ConSrvInitConsoleSupport(VOID) +{ + DPRINT("CONSRV: ConSrvInitConsoleSupport()\n"); + + /* Initialize the console list and its lock */ + ConsoleListSize = 0; + ConsoleList = NULL; + RtlInitializeResource(&ListLock); + + /* Should call LoadKeyboardLayout */ +} + +NTSTATUS NTAPI +ConSrvInitTerminal(IN OUT PTERMINAL Terminal, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId); +NTSTATUS NTAPI +ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal); + NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, OUT PCONSOLE* NewConsole, @@ -164,8 +328,8 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, PCONSOLE Console; CONSOLE_INFO ConsoleInfo; SIZE_T Length = 0; - ULONG i = 0; - FRONTEND FrontEnd; + + TERMINAL Terminal; /* The ConSrv terminal for this console */ if (NewConsole == NULL || ConsoleStartInfo == NULL) return STATUS_INVALID_PARAMETER; @@ -185,39 +349,18 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length); ConsoleInfo.ConsoleTitle[Length] = L'\0'; - - /* - * Choose an adequate terminal front-end to load, and load it - */ - Status = STATUS_SUCCESS; - for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i) - { - DPRINT("CONSRV: Trying to load %s terminal emulator...\n", FrontEndLoadingMethods[i].FrontEndName); - Status = FrontEndLoadingMethods[i].FrontEndLoad(&FrontEnd, - &ConsoleInfo, - ConsoleStartInfo, - ConsoleLeaderProcessId); - if (NT_SUCCESS(Status)) - { - DPRINT("CONSRV: %s terminal emulator loaded successfully\n", FrontEndLoadingMethods[i].FrontEndName); - break; - } - else - { - DPRINT1("CONSRV: Loading %s terminal emulator failed, Status = 0x%08lx , continuing...\n", FrontEndLoadingMethods[i].FrontEndName, Status); - } - } - + /* 3. Initialize the ConSrv terminal */ + Status = ConSrvInitTerminal(&Terminal, + &ConsoleInfo, + ConsoleStartInfo, + ConsoleLeaderProcessId); if (!NT_SUCCESS(Status)) { - DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status); + DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n", Status); return Status; } + DPRINT("CONSRV: Terminal initialized\n"); - DPRINT("CONSRV: Frontend initialized\n"); - - -/******************************************************************************/ /* * 4. Load the remaining console settings via the registry. */ @@ -252,31 +395,53 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, /* Set-up the code page */ ConsoleInfo.CodePage = GetOEMCP(); -/******************************************************************************/ - Status = ConDrvInitConsole(&ConsoleHandle, - &Console, - &ConsoleInfo, - ConsoleLeaderProcessId); + /* Initialize a new console via the driver */ + Status = ConDrvInitConsole(&Console, &ConsoleInfo); if (!NT_SUCCESS(Status)) { DPRINT1("Creating a new console failed, Status = 0x%08lx\n", Status); - FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd); + ConSrvDeinitTerminal(&Terminal); return Status; } ASSERT(Console); DPRINT("Console initialized\n"); - Status = ConDrvRegisterFrontEnd(Console, &FrontEnd); + /*** Register ConSrv features ***/ + + /* Initialize process support */ + InitializeListHead(&Console->ProcessList); + Console->NotifiedLastCloseProcess = NULL; + Console->NotifyLastClose = FALSE; + + /* Initialize pausing support */ + Console->PauseFlags = 0; + InitializeListHead(&Console->ReadWaitQueue); + InitializeListHead(&Console->WriteWaitQueue); + + /* Initialize the alias and history buffers */ + Console->Aliases = NULL; + InitializeListHead(&Console->HistoryBuffers); + Console->HistoryBufferSize = ConsoleInfo.HistoryBufferSize; + Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers; + Console->HistoryNoDup = ConsoleInfo.HistoryNoDup; + + Console->QuickEdit = ConsoleInfo.QuickEdit; + + /* Attach the ConSrv terminal to the console */ + Status = ConDrvRegisterTerminal(Console, &Terminal); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to register frontend to the given console, Status = 0x%08lx\n", Status); + DPRINT1("Failed to register terminal to the given console, Status = 0x%08lx\n", Status); ConDrvDeleteConsole(Console); - FrontEndLoadingMethods[i].FrontEndUnload(&FrontEnd); + ConSrvDeinitTerminal(&Terminal); return Status; } - DPRINT("FrontEnd registered\n"); + DPRINT("Terminal registered\n"); + + /* All went right, so add the console to the list */ + Status = InsertConsole(&ConsoleHandle, Console); /* Return the newly created console to the caller and a success code too */ *NewConsoleHandle = ConsoleHandle; @@ -289,11 +454,160 @@ ConSrvDeleteConsole(PCONSOLE Console) { DPRINT("ConSrvDeleteConsole\n"); - /* Just call the driver. ConSrvDeregisterFrontEnd is called on-demand. */ + // FIXME: Send a terminate message to all the processes owning this console + + /* Remove the console from the list */ + RemoveConsoleByPointer(Console); + + /* Clean aliases and history */ + IntDeleteAllAliases(Console); + HistoryDeleteBuffers(Console); + + /* Now, call the driver. ConDrvDeregisterTerminal is called on-demand. */ ConDrvDeleteConsole(Console); } + + + + +static NTSTATUS +ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, + IN PCONSOLE_PROCESS_DATA ProcessData, + IN ULONG Timeout) +{ + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess); + + if (ProcessData->CtrlDispatcher) + { + _SEH2_TRY + { + HANDLE Thread = NULL; + + _SEH2_TRY + { + Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, + ProcessData->CtrlDispatcher, + UlongToPtr(CtrlEvent), 0, NULL); + if (NULL == Thread) + { + Status = RtlGetLastNtStatus(); + DPRINT1("Failed thread creation, Status = 0x%08lx\n", Status); + } + else + { + DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); + WaitForSingleObject(Thread, Timeout); + } + } + _SEH2_FINALLY + { + CloseHandle(Thread); + } + _SEH2_END; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = 0x%08lx\n", Status); + } + _SEH2_END; + } + + return Status; +} + +NTSTATUS +ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent, + IN PCONSOLE_PROCESS_DATA ProcessData) +{ + return ConSrvConsoleCtrlEventTimeout(CtrlEvent, ProcessData, 0); +} + +PCONSOLE_PROCESS_DATA NTAPI +ConSrvGetConsoleLeaderProcess(IN PCONSOLE Console) +{ + if (Console == NULL) return NULL; + + return CONTAINING_RECORD(Console->ProcessList.Blink, + CONSOLE_PROCESS_DATA, + ConsoleLink); +} + +NTSTATUS NTAPI +ConSrvGetConsoleProcessList(IN PCONSOLE Console, + IN OUT PULONG ProcessIdsList, + IN ULONG MaxIdListItems, + OUT PULONG ProcessIdsTotal) +{ + PCONSOLE_PROCESS_DATA current; + PLIST_ENTRY current_entry; + + if (Console == NULL || ProcessIdsList == NULL || ProcessIdsTotal == NULL) + return STATUS_INVALID_PARAMETER; + + *ProcessIdsTotal = 0; + + for (current_entry = Console->ProcessList.Flink; + current_entry != &Console->ProcessList; + current_entry = current_entry->Flink) + { + current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink); + if (++(*ProcessIdsTotal) <= MaxIdListItems) + { + *ProcessIdsList++ = HandleToUlong(current->Process->ClientId.UniqueProcess); + } + } + + return STATUS_SUCCESS; +} + +// ConSrvGenerateConsoleCtrlEvent +NTSTATUS NTAPI +ConSrvConsoleProcessCtrlEvent(IN PCONSOLE Console, + IN ULONG ProcessGroupId, + IN ULONG CtrlEvent) +{ + NTSTATUS Status = STATUS_SUCCESS; + PLIST_ENTRY current_entry; + PCONSOLE_PROCESS_DATA current; + + /* If the console is already being destroyed, just return */ + if (!ConDrvValidateConsoleState(Console, CONSOLE_RUNNING)) + return STATUS_UNSUCCESSFUL; + + /* + * Loop through the process list, from the most recent process + * (the active one) to the oldest one (the first created, i.e. + * the console leader process), and for each, send an event + * (new processes are inserted at the head of the console process list). + */ + current_entry = Console->ProcessList.Flink; + while (current_entry != &Console->ProcessList) + { + current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink); + current_entry = current_entry->Flink; + + /* + * Only processes belonging to the same process group are signaled. + * If the process group ID is zero, then all the processes are signaled. + */ + if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId) + { + Status = ConSrvConsoleCtrlEvent(CtrlEvent, current); + } + } + + return Status; +} + + + + + /* PUBLIC SERVER APIS *********************************************************/ CSR_API(SrvAllocConsole) @@ -331,7 +645,7 @@ CSR_API(SrvAllocConsole) /* Return the console handle and the input wait handle to the caller */ AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle; - AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent; + AllocConsoleRequest->InputWaitHandle = ProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher; @@ -408,7 +722,7 @@ CSR_API(SrvAttachConsole) /* Return the console handle and the input wait handle to the caller */ AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle; - AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent; + AttachConsoleRequest->InputWaitHandle = TargetProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher; @@ -591,11 +905,6 @@ CSR_API(SrvSetConsoleCP) return Status; } -NTSTATUS NTAPI -ConDrvGetConsoleProcessList(IN PCONSOLE Console, - IN OUT PULONG ProcessIdsList, - IN ULONG MaxIdListItems, - OUT PULONG ProcessIdsTotal); CSR_API(SrvGetConsoleProcessList) { NTSTATUS Status; @@ -613,7 +922,7 @@ CSR_API(SrvGetConsoleProcessList) Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; - Status = ConDrvGetConsoleProcessList(Console, + Status = ConSrvGetConsoleProcessList(Console, GetProcessListRequest->ProcessIdsList, GetProcessListRequest->ProcessCount, &GetProcessListRequest->ProcessCount); @@ -631,7 +940,7 @@ CSR_API(SrvGenerateConsoleCtrlEvent) Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; - Status = ConDrvConsoleProcessCtrlEvent(Console, + Status = ConSrvConsoleProcessCtrlEvent(Console, GenerateCtrlEventRequest->ProcessGroupId, GenerateCtrlEventRequest->CtrlEvent); @@ -668,8 +977,18 @@ CSR_API(SrvConsoleNotifyLastClose) CSR_API(SrvGetConsoleMouseInfo) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PCONSOLE_GETMOUSEINFO GetMouseInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetMouseInfoRequest; + PCONSOLE Console; + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + /* Just retrieve the number of buttons of the mouse attached to this console */ + GetMouseInfoRequest->NumButtons = GetSystemMetrics(SM_CMOUSEBUTTONS); + + ConSrvReleaseConsole(Console, TRUE); + return STATUS_SUCCESS; } CSR_API(SrvSetConsoleKeyShortcuts) diff --git a/reactos/win32ss/user/winsrv/consrv/console.h b/reactos/win32ss/user/winsrv/consrv/console.h index d797920a5a5..a63754e4cbd 100644 --- a/reactos/win32ss/user/winsrv/consrv/console.h +++ b/reactos/win32ss/user/winsrv/consrv/console.h @@ -8,8 +8,8 @@ #pragma once -// FIXME: Fix compilation -struct _CONSOLE; +VOID NTAPI +ConSrvInitConsoleSupport(VOID); NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, @@ -18,8 +18,17 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, IN ULONG ConsoleLeaderProcessId); VOID NTAPI ConSrvDeleteConsole(struct _CONSOLE* /* PCONSOLE */ Console); -NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData, - struct _CONSOLE** /* PCONSOLE* */ Console, - BOOL LockConsole); -VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* /* PCONSOLE */ Console, - BOOL WasConsoleLocked); +NTSTATUS +ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData, + OUT struct _CONSOLE** /* PCONSOLE* */ Console, + IN BOOLEAN LockConsole); +VOID +ConSrvReleaseConsole(IN struct _CONSOLE* /* PCONSOLE */ Console, + IN BOOLEAN WasConsoleLocked); + + +BOOLEAN NTAPI +ConSrvValidateConsole(OUT struct _CONSOLE** /* PCONSOLE* */ Console, + IN HANDLE ConsoleHandle, + IN CONSOLE_STATE ExpectedState, + IN BOOLEAN LockConsole); diff --git a/reactos/win32ss/user/winsrv/consrv/consrv.h b/reactos/win32ss/user/winsrv/consrv/consrv.h index b30e00994f0..57a0acfb792 100644 --- a/reactos/win32ss/user/winsrv/consrv/consrv.h +++ b/reactos/win32ss/user/winsrv/consrv/consrv.h @@ -51,12 +51,12 @@ typedef struct _CONSOLE_PROCESS_DATA { LIST_ENTRY ConsoleLink; PCSR_PROCESS Process; // Process owning this structure. - HANDLE ConsoleEvent; + HANDLE InputWaitHandle; HANDLE ConsoleHandle; HANDLE ParentConsoleHandle; - BOOL ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise. + BOOLEAN ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise. RTL_CRITICAL_SECTION HandleTableLock; ULONG HandleTableSize; diff --git a/reactos/win32ss/user/winsrv/consrv/frontendctl.c b/reactos/win32ss/user/winsrv/consrv/frontendctl.c index a4cf977b07e..e8545ecc3ab 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontendctl.c +++ b/reactos/win32ss/user/winsrv/consrv/frontendctl.c @@ -30,7 +30,7 @@ * with NT's, but values are not. */ #if 0 -static NTSTATUS FASTCALL +static NTSTATUS SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState) { DPRINT1("Console Hardware State: %d\n", ConsoleHwState); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c index 5e04d1e3d7b..68d6579a0f2 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c @@ -48,7 +48,7 @@ SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData) PCONSOLE_PROCESS_DATA ProcessData; CLIENT_ID ConsoleLeaderCID; - ProcessData = ConDrvGetConsoleLeaderProcess(GuiData->Console); + ProcessData = ConSrvGetConsoleLeaderProcess(GuiData->Console); ConsoleLeaderCID = ProcessData->Process->ClientId; SetWindowLongPtrW(GuiData->hWindow, GWLP_CONSOLE_LEADER_PID, (LONG_PTR)(ConsoleLeaderCID.UniqueProcess)); @@ -610,7 +610,6 @@ GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData); static VOID OnActivate(PGUI_CONSOLE_DATA GuiData, WPARAM wParam) { - PCONSOLE Console = GuiData->Console; WORD ActivationState = LOWORD(wParam); DPRINT1("WM_ACTIVATE - ActivationState = %d\n"); @@ -637,12 +636,11 @@ OnActivate(PGUI_CONSOLE_DATA GuiData, WPARAM wParam) } /* - * When we are in QuickEdit mode, ignore the next mouse signal - * when we are going to be enabled again via the mouse, in order - * to prevent e.g. an erroneous right-click from the user which - * would have as an effect to paste some unwanted text... + * Ignore the next mouse signal when we are going to be enabled again via + * the mouse, in order to prevent, e.g. when we are in Edit mode, erroneous + * mouse actions from the user that could spoil text selection or copy/pastes. */ - if (Console->QuickEdit && (ActivationState == WA_CLICKACTIVE)) + if (ActivationState == WA_CLICKACTIVE) GuiData->IgnoreNextMouseSignal = TRUE; } @@ -947,12 +945,10 @@ GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer, static VOID OnPaint(PGUI_CONSOLE_DATA GuiData) { - PCONSOLE_SCREEN_BUFFER ActiveBuffer; + PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; PAINTSTRUCT ps; RECT rcPaint; - ActiveBuffer = GuiData->ActiveBuffer; - BeginPaint(GuiData->hWindow, &ps); if (ps.hdc != NULL && ps.rcPaint.left < ps.rcPaint.right && @@ -1325,7 +1321,7 @@ OnClose(PGUI_CONSOLE_DATA GuiData) * We shouldn't wait here, though, since the console lock is entered. * A copy of the thread list probably needs to be made. */ - ConDrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT); + ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT); LeaveCriticalSection(&Console->Lock); return FALSE; @@ -1386,15 +1382,18 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam) BOOL Err = FALSE; PCONSOLE Console = GuiData->Console; + // FIXME: It's here that we need to check whether we has focus or not + // and whether we are in edit mode or not, to know if we need to deal + // with the mouse, or not. + if (GuiData->IgnoreNextMouseSignal) { if (msg != WM_LBUTTONDOWN && msg != WM_MBUTTONDOWN && - msg != WM_RBUTTONDOWN && - msg != WM_MOUSEMOVE) + msg != WM_RBUTTONDOWN) { /* - * If this mouse signal is not a button-down action or a move, + * If this mouse signal is not a button-down action * then it is the last signal being ignored. */ GuiData->IgnoreNextMouseSignal = FALSE; @@ -1402,7 +1401,7 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam) else { /* - * This mouse signal is a button-down action or a move. + * This mouse signal is a button-down action. * Ignore it and perform default action. */ Err = TRUE; @@ -1610,6 +1609,20 @@ OnMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam) break; } + /* + * HACK FOR CORE-8394: Ignore the next mouse move signal + * just after mouse down click actions. + */ + switch (msg) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + GuiData->IgnoreNextMouseSignal = TRUE; + default: + break; + } + if (!Err) { if (wKeyState & MK_LBUTTON) @@ -1832,7 +1845,6 @@ OnMove(PGUI_CONSOLE_DATA GuiData) // HACK: This functionality is standard for general scrollbars. Don't add it by hand. VOID -FASTCALL GuiConsoleHandleScrollbarMenu(VOID) { HMENU hMenu; @@ -2071,7 +2083,7 @@ ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Detect Alt-Esc/Space/Tab presses defer to DefWindowProc */ if ( (HIWORD(lParam) & KF_ALTDOWN) && (wParam == VK_ESCAPE || wParam == VK_SPACE || wParam == VK_TAB)) { - return DefWindowProcW(hWnd, msg, wParam, lParam); + return DefWindowProcW(hWnd, msg, wParam, lParam); } OnKey(GuiData, msg, wParam, lParam); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c index 457a6c496c6..ce84523db6a 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c @@ -357,7 +357,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* Get the console leader process, our client */ - ProcessData = ConDrvGetConsoleLeaderProcess(Console); + ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for the client */ Status = NtDuplicateObject(NtCurrentProcess(), @@ -433,7 +433,7 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ - ProcessData = ConDrvGetConsoleLeaderProcess(Console); + ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, @@ -457,7 +457,7 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, &ViewSize, ViewUnmap, 0, - PAGE_READONLY); + PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = %lu\n", Status); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c index 9479917c4ea..6fb343a324d 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c @@ -433,7 +433,7 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n"); return STATUS_UNSUCCESSFUL; } - ///// /* HACK */ Console->TermIFace.Data = (PVOID)GuiData; /* HACK */ + ///// /* HACK */ Console->FrontEndIFace.Data = (PVOID)GuiData; /* HACK */ GuiData->Console = Console; GuiData->ActiveBuffer = Console->ActiveBuffer; GuiData->hWindow = NULL; @@ -802,25 +802,6 @@ GuiReleaseScreenBuffer(IN OUT PFRONTEND This, } } -static BOOL NTAPI -GuiProcessKeyCallback(IN OUT PFRONTEND This, - MSG* msg, - BYTE KeyStateMenu, - DWORD ShiftState, - UINT VirtualKeyCode, - BOOL Down) -{ - if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyStateMenu & 0x80) && - (VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE)) - { - DPRINT1("GuiProcessKeyCallback\n"); - //DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam); - //return TRUE; - } - - return FALSE; -} - static BOOL NTAPI GuiSetMouseCursor(IN OUT PFRONTEND This, HCURSOR CursorHandle); @@ -1105,7 +1086,6 @@ static FRONTEND_VTBL GuiVtbl = GuiResizeTerminal, GuiSetActiveScreenBuffer, GuiReleaseScreenBuffer, - GuiProcessKeyCallback, GuiRefreshInternalInfo, GuiChangeTitle, GuiChangeIcon, diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h index 67d7871728d..b70efa96a6f 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h @@ -14,7 +14,7 @@ #include "guisettings.h" #include "conwnd.h" -NTSTATUS FASTCALL GuiInitConsole(PCONSOLE Console, +NTSTATUS GuiInitConsole(PCONSOLE Console, /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo, PCONSOLE_INFO ConsoleInfo, DWORD ProcessId, diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/input.c b/reactos/win32ss/user/winsrv/consrv/frontends/input.c index 17b7ff39cab..2fb6f3b8071 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/input.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/input.c @@ -20,7 +20,78 @@ /* PRIVATE FUNCTIONS **********************************************************/ -static DWORD FASTCALL +static VOID +ConDrvProcessKey(IN PCONSOLE Console, + IN BOOLEAN Down, + IN UINT VirtualKeyCode, + IN UINT VirtualScanCode, + IN WCHAR UnicodeChar, + IN ULONG ShiftState, + IN BYTE KeyStateCtrl) +{ + INPUT_RECORD er; + + /* process Ctrl-C and Ctrl-Break */ + if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && + Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && + (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) ) + { + DPRINT1("Console_Api Ctrl-C\n"); + ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); + + if (Console->LineBuffer && !Console->LineComplete) + { + /* Line input is in progress; end it */ + Console->LinePos = Console->LineSize = 0; + Console->LineComplete = TRUE; + } + return; + } + + if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && + (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) ) + { + if (!Down) return; + + /* scroll up or down */ + if (VK_UP == VirtualKeyCode) + { + /* only scroll up if there is room to scroll up into */ + if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) + { + Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + + Console->ActiveBuffer->ScreenBufferSize.Y - 1) % + Console->ActiveBuffer->ScreenBufferSize.Y; + Console->ActiveBuffer->CursorPosition.Y++; + } + } + else + { + /* only scroll down if there is room to scroll down into */ + if (Console->ActiveBuffer->CursorPosition.Y != 0) + { + Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % + Console->ActiveBuffer->ScreenBufferSize.Y; + Console->ActiveBuffer->CursorPosition.Y--; + } + } + + ConioDrawConsole(Console); + return; + } + + er.EventType = KEY_EVENT; + er.Event.KeyEvent.bKeyDown = Down; + er.Event.KeyEvent.wRepeatCount = 1; + er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; + er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; + er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; + er.Event.KeyEvent.dwControlKeyState = ShiftState; + + ConioProcessInputEvent(Console, &er); +} + +static DWORD ConioGetShiftState(PBYTE KeyState, LPARAM lParam) { DWORD ssOut = 0; @@ -104,16 +175,6 @@ ConioProcessKey(PCONSOLE Console, MSG* msg) UnicodeChar = (1 == RetChars ? Chars[0] : 0); } - if (TermProcessKeyCallback(Console, - msg, - KeyState[VK_MENU], - ShiftState, - VirtualKeyCode, - Down)) - { - return; - } - Fake = UnicodeChar && (msg->message != WM_CHAR && msg->message != WM_SYSCHAR && msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP); @@ -143,4 +204,14 @@ ConioProcessKey(PCONSOLE Console, MSG* msg) KeyState[VK_CONTROL]); } +DWORD +ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale) +{ + DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; + /* If line input in progress, perhaps adjust for insert toggle */ + if (Console->LineBuffer && !Console->LineComplete && (Console->InsertMode ? !Console->LineInsertToggle : Console->LineInsertToggle)) + return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); + return Size; +} + /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c b/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c new file mode 100644 index 00000000000..b2ba1a95885 --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c @@ -0,0 +1,363 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: frontends/terminal.c + * PURPOSE: ConSrv terminal. + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #include "frontends/gui/guiterm.h" +#ifdef TUITERM_COMPILE +#include "frontends/tui/tuiterm.h" +#endif + +#define NDEBUG +#include + +/* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/ + +/***************/ +#ifdef TUITERM_COMPILE +NTSTATUS NTAPI +TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId); +NTSTATUS NTAPI +TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd); +#endif + +NTSTATUS NTAPI +GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId); +NTSTATUS NTAPI +GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd); +/***************/ + +typedef +NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId); + +typedef +NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd); + +/* + * If we are not in GUI-mode, start the text-mode terminal emulator. + * If we fail, try to start the GUI-mode terminal emulator. + * + * Try to open the GUI-mode terminal emulator. Two cases are possible: + * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case + * failed and we start GUI-mode terminal emulator. + * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case + * succeeded BUT we failed at starting text-mode terminal emulator. + * Then GuiMode was switched to TRUE in order to try to open the GUI-mode + * terminal emulator (Win32k will automatically switch to graphical mode, + * therefore no additional code is needed). + */ + +/* + * NOTE: Each entry of the table should be retrieved when loading a front-end + * (examples of the CSR servers which register some data for CSRSS). + */ +struct +{ + CHAR FrontEndName[80]; + FRONTEND_LOAD FrontEndLoad; + FRONTEND_UNLOAD FrontEndUnload; +} FrontEndLoadingMethods[] = +{ +#ifdef TUITERM_COMPILE + {"TUI", TuiLoadFrontEnd, TuiUnloadFrontEnd}, +#endif + {"GUI", GuiLoadFrontEnd, GuiUnloadFrontEnd}, + +// {"Not found", 0, NULL} +}; + +static NTSTATUS +ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG i; + + /* + * Choose an adequate terminal front-end to load, and load it + */ + for (i = 0; i < sizeof(FrontEndLoadingMethods) / sizeof(FrontEndLoadingMethods[0]); ++i) + { + DPRINT("CONSRV: Trying to load %s frontend...\n", + FrontEndLoadingMethods[i].FrontEndName); + Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd, + ConsoleInfo, + ExtraConsoleInfo, + ProcessId); + if (NT_SUCCESS(Status)) + { + /* Save the unload callback */ + FrontEnd->UnloadFrontEnd = FrontEndLoadingMethods[i].FrontEndUnload; + + DPRINT("CONSRV: %s frontend loaded successfully\n", + FrontEndLoadingMethods[i].FrontEndName); + break; + } + else + { + DPRINT1("CONSRV: Loading %s frontend failed, Status = 0x%08lx , continuing...\n", + FrontEndLoadingMethods[i].FrontEndName, Status); + } + } + + return Status; +} + +static NTSTATUS +ConSrvUnloadFrontEnd(IN PFRONTEND FrontEnd) +{ + if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER; + // return FrontEnd->Vtbl->UnloadFrontEnd(FrontEnd); + return FrontEnd->UnloadFrontEnd(FrontEnd); +} + +// See after... +static TERMINAL_VTBL ConSrvTermVtbl; + +NTSTATUS NTAPI +ConSrvInitTerminal(IN OUT PTERMINAL Terminal, + IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PVOID ExtraConsoleInfo, + IN ULONG ProcessId) +{ + NTSTATUS Status; + PFRONTEND FrontEnd; + + /* Load a suitable frontend for the ConSrv terminal */ + FrontEnd = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*FrontEnd)); + if (!FrontEnd) return STATUS_NO_MEMORY; + + Status = ConSrvLoadFrontEnd(FrontEnd, + ConsoleInfo, + ExtraConsoleInfo, + ProcessId); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status); + ConsoleFreeHeap(FrontEnd); + return Status; + } + DPRINT("CONSRV: Frontend initialized\n"); + + /* Initialize the ConSrv terminal */ + Terminal->Vtbl = &ConSrvTermVtbl; + // Terminal->Console will be initialized by ConDrvRegisterTerminal + Terminal->Data = FrontEnd; /* We store the frontend pointer in the terminal private data */ + + return STATUS_SUCCESS; +} + +NTSTATUS NTAPI +ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal) +{ + NTSTATUS Status = STATUS_SUCCESS; + PFRONTEND FrontEnd = Terminal->Data; + + /* Reset the ConSrv terminal */ + Terminal->Data = NULL; + Terminal->Vtbl = NULL; + + /* Unload the frontend */ + if (FrontEnd != NULL) + { + Status = ConSrvUnloadFrontEnd(FrontEnd); + ConsoleFreeHeap(FrontEnd); + } + + return Status; +} + + +/* CONSRV TERMINAL INTERFACE **************************************************/ + +static NTSTATUS NTAPI +ConSrvTermInitTerminal(IN OUT PTERMINAL This, + IN PCONSOLE Console) +{ + NTSTATUS Status; + PFRONTEND FrontEnd = This->Data; + + /* Initialize the console pointer for our frontend */ + FrontEnd->Console = Console; + + /** HACK HACK!! Copy FrontEnd into the console!! **/ + DPRINT1("Using FrontEndIFace HACK(1), should be removed after proper implementation!\n"); + Console->FrontEndIFace = *FrontEnd; + + Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, FrontEnd->Console); + + /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/ + DPRINT1("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n"); + Console->FrontEndIFace = *FrontEnd; + + return Status; +} + +static VOID NTAPI +ConSrvTermDeinitTerminal(IN OUT PTERMINAL This) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->DeinitFrontEnd(FrontEnd); +} + +static VOID NTAPI +ConSrvTermDrawRegion(IN OUT PTERMINAL This, + SMALL_RECT* Region) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->DrawRegion(FrontEnd, Region); +} + +static VOID NTAPI +ConSrvTermWriteStream(IN OUT PTERMINAL This, + SMALL_RECT* Region, + SHORT CursorStartX, + SHORT CursorStartY, + UINT ScrolledLines, + PWCHAR Buffer, + UINT Length) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->WriteStream(FrontEnd, + Region, + CursorStartX, + CursorStartY, + ScrolledLines, + Buffer, + Length); +} + +static BOOL NTAPI +ConSrvTermSetCursorInfo(IN OUT PTERMINAL This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer) +{ + PFRONTEND FrontEnd = This->Data; + return FrontEnd->Vtbl->SetCursorInfo(FrontEnd, ScreenBuffer); +} + +static BOOL NTAPI +ConSrvTermSetScreenInfo(IN OUT PTERMINAL This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer, + SHORT OldCursorX, + SHORT OldCursorY) +{ + PFRONTEND FrontEnd = This->Data; + return FrontEnd->Vtbl->SetScreenInfo(FrontEnd, + ScreenBuffer, + OldCursorX, + OldCursorY); +} + +static VOID NTAPI +ConSrvTermResizeTerminal(IN OUT PTERMINAL This) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->ResizeTerminal(FrontEnd); +} + +static VOID NTAPI +ConSrvTermSetActiveScreenBuffer(IN OUT PTERMINAL This) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->SetActiveScreenBuffer(FrontEnd); +} + +static VOID NTAPI +ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This, + IN PCONSOLE_SCREEN_BUFFER ScreenBuffer) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer); +} + +static VOID NTAPI +ConSrvTermChangeTitle(IN OUT PTERMINAL This) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->ChangeTitle(FrontEnd); +} + +static VOID NTAPI +ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This, + PCOORD pSize) +{ + PFRONTEND FrontEnd = This->Data; + FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize); +} + +/* +static BOOL NTAPI +ConSrvTermGetSelectionInfo(IN OUT PTERMINAL This, + PCONSOLE_SELECTION_INFO pSelectionInfo) +{ + PFRONTEND FrontEnd = This->Data; + return FrontEnd->Vtbl->GetSelectionInfo(FrontEnd, pSelectionInfo); +} +*/ + +static BOOL NTAPI +ConSrvTermSetPalette(IN OUT PTERMINAL This, + HPALETTE PaletteHandle, + UINT PaletteUsage) +{ + PFRONTEND FrontEnd = This->Data; + return FrontEnd->Vtbl->SetPalette(FrontEnd, PaletteHandle, PaletteUsage); +} + +static INT NTAPI +ConSrvTermShowMouseCursor(IN OUT PTERMINAL This, + BOOL Show) +{ + PFRONTEND FrontEnd = This->Data; + return FrontEnd->Vtbl->ShowMouseCursor(FrontEnd, Show); +} + +static TERMINAL_VTBL ConSrvTermVtbl = +{ + ConSrvTermInitTerminal, + ConSrvTermDeinitTerminal, + ConSrvTermDrawRegion, + ConSrvTermWriteStream, + ConSrvTermSetCursorInfo, + ConSrvTermSetScreenInfo, + ConSrvTermResizeTerminal, + ConSrvTermSetActiveScreenBuffer, + ConSrvTermReleaseScreenBuffer, + ConSrvTermChangeTitle, + ConSrvTermGetLargestConsoleWindowSize, + // ConSrvTermGetSelectionInfo, + ConSrvTermSetPalette, + ConSrvTermShowMouseCursor, +}; + +#if 0 +VOID +ResetFrontEnd(IN PCONSOLE Console) +{ + if (!Console) return; + + /* Reinitialize the frontend interface */ + RtlZeroMemory(&Console->FrontEndIFace, sizeof(Console->FrontEndIFace)); + Console->FrontEndIFace.Vtbl = &ConSrvTermVtbl; +} +#endif + +/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c index 51fbd842506..1231148afb5 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c @@ -24,13 +24,6 @@ /* GLOBALS ********************************************************************/ -#define GetNextConsole(Console) \ - CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry) - -#define GetPrevConsole(Console) \ - CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry) - - /* TUI Console Window Class name */ #define TUI_CONSOLE_WINDOW_CLASS L"TuiConsoleWindowClass" @@ -46,6 +39,13 @@ typedef struct _TUI_CONSOLE_DATA // TUI_CONSOLE_INFO TuiInfo; /* TUI terminal settings */ } TUI_CONSOLE_DATA, *PTUI_CONSOLE_DATA; +#define GetNextConsole(Console) \ + CONTAINING_RECORD(Console->Entry.Flink, TUI_CONSOLE_DATA, Entry) + +#define GetPrevConsole(Console) \ + CONTAINING_RECORD(Console->Entry.Blink, TUI_CONSOLE_DATA, Entry) + + /* List of the maintained virtual consoles and its lock */ static LIST_ENTRY VirtConsList; static PTUI_CONSOLE_DATA ActiveConsole; /* The active console on screen */ @@ -164,7 +164,7 @@ done: /**\ \******************************************************************************/ -static BOOL FASTCALL +static BOOL TuiSwapConsole(INT Next) { static PTUI_CONSOLE_DATA SwapConsole = NULL; /* Console we are thinking about swapping with */ @@ -231,7 +231,7 @@ TuiSwapConsole(INT Next) } } -static VOID FASTCALL +static VOID TuiCopyRect(PCHAR Dest, PTEXTMODE_SCREEN_BUFFER Buff, SMALL_RECT* Region) { UINT SrcDelta, DestDelta; @@ -276,6 +276,21 @@ TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_KEYUP: case WM_SYSKEYUP: { +#if 0 + if ((HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_TAB) + { + // if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT) + TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1); + + break; + } + else if (wParam == VK_MENU /* && !Down */) + { + TuiSwapConsole(0); + break; + } +#endif + if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE)) { MSG Message; @@ -459,7 +474,7 @@ TuiInitFrontEnd(IN OUT PFRONTEND This, // return STATUS_INVALID_PARAMETER; // /* Initialize the console */ - // Console->TermIFace.Vtbl = &TuiVtbl; + // Console->FrontEndIFace.Vtbl = &TuiVtbl; TuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(TUI_CONSOLE_DATA)); if (!TuiData) @@ -467,7 +482,7 @@ TuiInitFrontEnd(IN OUT PFRONTEND This, DPRINT1("CONSRV: Failed to create TUI_CONSOLE_DATA\n"); return STATUS_UNSUCCESSFUL; } - // Console->TermIFace.Data = (PVOID)TuiData; + // Console->FrontEndIFace.Data = (PVOID)TuiData; TuiData->Console = Console; TuiData->hWindow = NULL; @@ -525,7 +540,7 @@ static VOID NTAPI TuiDeinitFrontEnd(IN OUT PFRONTEND This) { // PCONSOLE Console = This->Console; - PTUI_CONSOLE_DATA TuiData = This->Data; // Console->TermIFace.Data; + PTUI_CONSOLE_DATA TuiData = This->Data; // Console->FrontEndIFace.Data; /* Close the notification window */ DestroyWindow(TuiData->hWindow); @@ -556,7 +571,7 @@ TuiDeinitFrontEnd(IN OUT PFRONTEND This) /* Switch to the next console */ if (NULL != ActiveConsole) ConioDrawConsole(ActiveConsole->Console); - // Console->TermIFace.Data = NULL; + // Console->FrontEndIFace.Data = NULL; This->Data = NULL; DeleteCriticalSection(&TuiData->Lock); ConsoleFreeHeap(TuiData); @@ -688,32 +703,6 @@ TuiResizeTerminal(IN OUT PFRONTEND This) { } -static BOOL NTAPI -TuiProcessKeyCallback(IN OUT PFRONTEND This, - MSG* msg, - BYTE KeyStateMenu, - DWORD ShiftState, - UINT VirtualKeyCode, - BOOL Down) -{ - if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) && - VK_TAB == VirtualKeyCode) - { - if (Down) - { - TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1); - } - - return TRUE; - } - else if (VK_MENU == VirtualKeyCode && !Down) - { - return TuiSwapConsole(0); - } - - return FALSE; -} - static VOID NTAPI TuiRefreshInternalInfo(IN OUT PFRONTEND This) { @@ -814,7 +803,6 @@ static FRONTEND_VTBL TuiVtbl = TuiSetCursorInfo, TuiSetScreenInfo, TuiResizeTerminal, - TuiProcessKeyCallback, TuiRefreshInternalInfo, TuiChangeTitle, TuiChangeIcon, diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.h b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.h index 8abbcb9810b..2a176dc6cfe 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.h @@ -11,7 +11,7 @@ #pragma once -NTSTATUS FASTCALL TuiInitConsole(PCONSOLE Console, +NTSTATUS TuiInitConsole(PCONSOLE Console, /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo, PCONSOLE_INFO ConsoleInfo, DWORD ProcessId); diff --git a/reactos/win32ss/user/winsrv/consrv/handle.c b/reactos/win32ss/user/winsrv/consrv/handle.c index 98b7ff0c0db..721f3375558 100644 --- a/reactos/win32ss/user/winsrv/consrv/handle.c +++ b/reactos/win32ss/user/winsrv/consrv/handle.c @@ -72,7 +72,8 @@ ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry) */ if (Object->Type == INPUT_BUFFER) { - PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; + // PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; + PCONSOLE Console = Object->Console; /* * Wake up all the writing waiters related to this handle for this @@ -83,13 +84,13 @@ ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry) * whether or not they are related to this handle and if so, they * return. */ - CsrNotifyWait(&InputBuffer->ReadWaitQueue, + CsrNotifyWait(&Console->ReadWaitQueue, TRUE, NULL, (PVOID)Entry); - if (!IsListEmpty(&InputBuffer->ReadWaitQueue)) + if (!IsListEmpty(&Console->ReadWaitQueue)) { - CsrDereferenceWait(&InputBuffer->ReadWaitQueue); + CsrDereferenceWait(&Console->ReadWaitQueue); } } @@ -290,7 +291,6 @@ ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData) } VOID -FASTCALL ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object, IN CONSOLE_IO_OBJECT_TYPE Type, IN PCONSOLE Console) @@ -306,7 +306,6 @@ ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object, } NTSTATUS -FASTCALL ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE Handle, PCONSOLE_IO_OBJECT Object, @@ -372,7 +371,6 @@ ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData, } NTSTATUS -FASTCALL ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData, HANDLE Handle) { @@ -399,7 +397,6 @@ ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData, } NTSTATUS -FASTCALL ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, HANDLE Handle, PCONSOLE_IO_OBJECT* Object, @@ -443,7 +440,7 @@ ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - // Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole); + // Status = ConSrvGetConsole(ProcessData, &ObjectConsole, LockConsole); // if (NT_SUCCESS(Status)) if (ConDrvValidateConsoleUnsafe(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole)) { @@ -464,7 +461,6 @@ ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, } VOID -FASTCALL ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object, BOOL IsConsoleLocked) { @@ -472,7 +468,6 @@ ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object, } NTSTATUS -FASTCALL ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE pInputHandle, PHANDLE pOutputHandle, @@ -527,7 +522,7 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, Status = NtDuplicateObject(NtCurrentProcess(), Console->InputBuffer.ActiveEvent, ProcessData->Process->ProcessHandle, - &ProcessData->ConsoleEvent, + &ProcessData->InputWaitHandle, EVENT_ALL_ACCESS, 0, 0); if (!NT_SUCCESS(Status)) { @@ -551,7 +546,6 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, } NTSTATUS -FASTCALL ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, HANDLE ConsoleHandle, BOOL CreateNewHandlesTable, @@ -563,7 +557,7 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, PCONSOLE Console; /* Validate and lock the console */ - if (!ConDrvValidateConsole(&Console, + if (!ConSrvValidateConsole(&Console, ConsoleHandle, CONSOLE_RUNNING, TRUE)) { @@ -606,7 +600,7 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, Status = NtDuplicateObject(NtCurrentProcess(), Console->InputBuffer.ActiveEvent, ProcessData->Process->ProcessHandle, - &ProcessData->ConsoleEvent, + &ProcessData->InputWaitHandle, EVENT_ALL_ACCESS, 0, 0); if (!NT_SUCCESS(Status)) { @@ -634,7 +628,6 @@ Quit: } VOID -FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) { PCONSOLE Console; @@ -644,12 +637,12 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) // RtlEnterCriticalSection(&ProcessData->HandleTableLock); /* Validate and lock the console */ - if (ConDrvValidateConsole(&Console, + if (ConSrvValidateConsole(&Console, ProcessData->ConsoleHandle, CONSOLE_RUNNING, TRUE)) { /* Retrieve the console leader process */ - PCONSOLE_PROCESS_DATA ConsoleLeaderProcess = ConDrvGetConsoleLeaderProcess(Console); + PCONSOLE_PROCESS_DATA ConsoleLeaderProcess = ConSrvGetConsoleLeaderProcess(Console); DPRINT("ConSrvRemoveConsole - Locking OK\n"); @@ -684,7 +677,7 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) * and then send the last close notification. */ Console->NotifyLastClose = FALSE; - ConDrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess); + ConSrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess); /* Only now, reset the pointer */ Console->NotifiedLastCloseProcess = NULL; @@ -696,9 +689,9 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) /* Release the console */ DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount); - ConDrvReleaseConsole(Console, TRUE); - //CloseHandle(ProcessData->ConsoleEvent); - //ProcessData->ConsoleEvent = NULL; + ConSrvReleaseConsole(Console, TRUE); + //CloseHandle(ProcessData->InputWaitHandle); + //ProcessData->InputWaitHandle = NULL; } // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); diff --git a/reactos/win32ss/user/winsrv/consrv/handle.h b/reactos/win32ss/user/winsrv/consrv/handle.h index c10948f92f5..2e75f884a4b 100644 --- a/reactos/win32ss/user/winsrv/consrv/handle.h +++ b/reactos/win32ss/user/winsrv/consrv/handle.h @@ -10,23 +10,23 @@ #pragma once -VOID FASTCALL ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object, +VOID ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object, IN CONSOLE_IO_OBJECT_TYPE Type, IN PCONSOLE Console); -NTSTATUS FASTCALL ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData, +NTSTATUS ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE Handle, PCONSOLE_IO_OBJECT Object, DWORD Access, BOOL Inheritable, DWORD ShareMode); -NTSTATUS FASTCALL ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData, +NTSTATUS ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData, HANDLE Handle); -NTSTATUS FASTCALL ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, +NTSTATUS ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, HANDLE Handle, PCONSOLE_IO_OBJECT* Object, PVOID* Entry OPTIONAL, DWORD Access, BOOL LockConsole, CONSOLE_IO_OBJECT_TYPE Type); -VOID FASTCALL ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object, +VOID ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object, BOOL IsConsoleLocked); diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio.h b/reactos/win32ss/user/winsrv/consrv/include/conio.h index 26b460cc63f..90defe0ea42 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/conio.h +++ b/reactos/win32ss/user/winsrv/consrv/include/conio.h @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Console Server DLL - * FILE: win32ss/user/winsrv/consrv/include/conio.h + * FILE: consrv/include/conio.h * PURPOSE: Public Console I/O Interface * PROGRAMMERS: Gé van Geldorp * Jeffrey Morlan @@ -10,6 +10,8 @@ #pragma once +#include "rect.h" + #define CSR_DEFAULT_CURSOR_SIZE 25 /* Default attributes */ @@ -64,8 +66,6 @@ struct _CONSOLE_SCREEN_BUFFER LIST_ENTRY ListEntry; /* Entry in console's list of buffers */ - // PVOID Data; /* Private data for the frontend to use */ - COORD ScreenBufferSize; /* Size of this screen buffer. (Rows, Columns) for text-mode and (Width, Height) for graphics-mode */ COORD ViewSize; /* Associated "view" (i.e. console) size */ @@ -90,6 +90,8 @@ struct _CONSOLE_SCREEN_BUFFER // WORD ScreenDefaultAttrib; /* Default screen char attribute */ // WORD PopupDefaultAttrib; /* Default popup char attribute */ USHORT Mode; /* Output buffer modes */ + + // PVOID Data; /* Private data for the frontend to use */ }; @@ -125,8 +127,8 @@ typedef struct _TEXTMODE_BUFFER_INFO COORD ScreenBufferSize; USHORT ScreenAttrib; USHORT PopupAttrib; - BOOLEAN IsCursorVisible; ULONG CursorSize; + BOOLEAN IsCursorVisible; } TEXTMODE_BUFFER_INFO, *PTEXTMODE_BUFFER_INFO; typedef struct _TEXTMODE_SCREEN_BUFFER @@ -158,6 +160,7 @@ typedef struct _GRAPHICS_SCREEN_BUFFER ULONG BitMapUsage; /* See the uUsage parameter of GetDIBits */ HANDLE hSection; /* Handle to the memory shared section for the bitmap buffer */ PVOID BitMap; /* Our bitmap buffer */ + PVOID ClientBitMap; /* A copy of the client view of our bitmap buffer */ HANDLE Mutex; /* Our mutex, used to synchronize read / writes to the bitmap buffer */ HANDLE ClientMutex; /* A copy of the client handle to our mutex */ @@ -173,97 +176,75 @@ typedef struct _CONSOLE_INPUT_BUFFER ULONG InputBufferSize; /* Size of this input buffer */ LIST_ENTRY InputEvents; /* List head for input event queue */ HANDLE ActiveEvent; /* Event set when an input event is added in its queue */ - LIST_ENTRY ReadWaitQueue; /* List head for the queue of read wait blocks */ USHORT Mode; /* Input buffer modes */ } CONSOLE_INPUT_BUFFER, *PCONSOLE_INPUT_BUFFER; -typedef struct _FRONTEND FRONTEND, *PFRONTEND; +typedef struct _TERMINAL TERMINAL, *PTERMINAL; /* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO; -typedef struct _FRONTEND_VTBL +typedef struct _TERMINAL_VTBL { /* * Internal interface (functions called by the console server only) */ - NTSTATUS (NTAPI *InitFrontEnd)(IN OUT PFRONTEND This, + NTSTATUS (NTAPI *InitTerminal)(IN OUT PTERMINAL This, IN struct _CONSOLE* Console); - VOID (NTAPI *DeinitFrontEnd)(IN OUT PFRONTEND This); + VOID (NTAPI *DeinitTerminal)(IN OUT PTERMINAL This); /* Interface used for both text-mode and graphics screen buffers */ - VOID (NTAPI *DrawRegion)(IN OUT PFRONTEND This, + VOID (NTAPI *DrawRegion)(IN OUT PTERMINAL This, SMALL_RECT* Region); /* Interface used only for text-mode screen buffers */ - VOID (NTAPI *WriteStream)(IN OUT PFRONTEND This, - SMALL_RECT* Block, + VOID (NTAPI *WriteStream)(IN OUT PTERMINAL This, + SMALL_RECT* Region, SHORT CursorStartX, SHORT CursorStartY, UINT ScrolledLines, PWCHAR Buffer, UINT Length); - BOOL (NTAPI *SetCursorInfo)(IN OUT PFRONTEND This, + BOOL (NTAPI *SetCursorInfo)(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer); - BOOL (NTAPI *SetScreenInfo)(IN OUT PFRONTEND This, + BOOL (NTAPI *SetScreenInfo)(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer, SHORT OldCursorX, SHORT OldCursorY); - VOID (NTAPI *ResizeTerminal)(IN OUT PFRONTEND This); - VOID (NTAPI *SetActiveScreenBuffer)(IN OUT PFRONTEND This); - VOID (NTAPI *ReleaseScreenBuffer)(IN OUT PFRONTEND This, + VOID (NTAPI *ResizeTerminal)(IN OUT PTERMINAL This); + VOID (NTAPI *SetActiveScreenBuffer)(IN OUT PTERMINAL This); + VOID (NTAPI *ReleaseScreenBuffer)(IN OUT PTERMINAL This, IN PCONSOLE_SCREEN_BUFFER ScreenBuffer); - BOOL (NTAPI *ProcessKeyCallback)(IN OUT PFRONTEND This, - MSG* msg, - BYTE KeyStateMenu, - DWORD ShiftState, - UINT VirtualKeyCode, - BOOL Down); - VOID (NTAPI *RefreshInternalInfo)(IN OUT PFRONTEND This); /* * External interface (functions corresponding to the Console API) */ - VOID (NTAPI *ChangeTitle)(IN OUT PFRONTEND This); - BOOL (NTAPI *ChangeIcon)(IN OUT PFRONTEND This, - HICON IconHandle); - HWND (NTAPI *GetConsoleWindowHandle)(IN OUT PFRONTEND This); - VOID (NTAPI *GetLargestConsoleWindowSize)(IN OUT PFRONTEND This, + VOID (NTAPI *ChangeTitle)(IN OUT PTERMINAL This); + VOID (NTAPI *GetLargestConsoleWindowSize)(IN OUT PTERMINAL This, PCOORD pSize); - BOOL (NTAPI *GetSelectionInfo)(IN OUT PFRONTEND This, - PCONSOLE_SELECTION_INFO pSelectionInfo); - BOOL (NTAPI *SetPalette)(IN OUT PFRONTEND This, + // BOOL (NTAPI *GetSelectionInfo)(IN OUT PTERMINAL This, + // PCONSOLE_SELECTION_INFO pSelectionInfo); + BOOL (NTAPI *SetPalette)(IN OUT PTERMINAL This, HPALETTE PaletteHandle, UINT PaletteUsage); - ULONG (NTAPI *GetDisplayMode)(IN OUT PFRONTEND This); - BOOL (NTAPI *SetDisplayMode)(IN OUT PFRONTEND This, - ULONG NewMode); - INT (NTAPI *ShowMouseCursor)(IN OUT PFRONTEND This, + INT (NTAPI *ShowMouseCursor)(IN OUT PTERMINAL This, BOOL Show); - BOOL (NTAPI *SetMouseCursor)(IN OUT PFRONTEND This, - HCURSOR CursorHandle); - HMENU (NTAPI *MenuControl)(IN OUT PFRONTEND This, - UINT CmdIdLow, - UINT CmdIdHigh); - BOOL (NTAPI *SetMenuClose)(IN OUT PFRONTEND This, - BOOL Enable); #if 0 // Possible future front-end interface - BOOL (NTAPI *GetFrontEndProperty)(IN OUT PFRONTEND This, + BOOL (NTAPI *GetTerminalProperty)(IN OUT PTERMINAL This, ULONG Flag, PVOID Info, ULONG Size); - BOOL (NTAPI *SetFrontEndProperty)(IN OUT PFRONTEND This, + BOOL (NTAPI *SetTerminalProperty)(IN OUT PTERMINAL This, ULONG Flag, PVOID Info /*, ULONG Size */); #endif -} FRONTEND_VTBL, *PFRONTEND_VTBL; +} TERMINAL_VTBL, *PTERMINAL_VTBL; -struct _FRONTEND +struct _TERMINAL { - PFRONTEND_VTBL Vtbl; /* Virtual table */ + PTERMINAL_VTBL Vtbl; /* Virtual table */ struct _CONSOLE* Console; /* Console to which the frontend is attached to */ PVOID Data; /* Private data */ - PVOID OldData; /* Reserved */ }; /* @@ -277,112 +258,109 @@ typedef enum _CONSOLE_STATE CONSOLE_IN_DESTRUCTION /* Console in destruction */ } CONSOLE_STATE, *PCONSOLE_STATE; +// HACK!! +struct _CONSOLE; +struct _WINSRV_CONSOLE; +/* HACK: */ typedef struct _CONSOLE *PCONSOLE; +#include "conio_winsrv.h" + typedef struct _CONSOLE { +/******************************* Console Set-up *******************************/ LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */ CRITICAL_SECTION Lock; + + /**/WINSRV_CONSOLE;/**/ // HACK HACK!! + CONSOLE_STATE State; /* State of the console */ + TERMINAL TermIFace; /* Frontend-specific interface */ - LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */ - PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that needs to be notified when the console leader process is killed */ - BOOLEAN NotifyLastClose; /* TRUE if the console should send a control event when the console leader process is killed */ - - FRONTEND TermIFace; /* Frontend-specific interface */ + ULONG ConsoleID; /* The ID of the console */ + LIST_ENTRY ListEntry; /* Entry in the list of consoles */ /**************************** Input buffer and data ***************************/ CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */ + UINT InputCodePage; - /** Put those things in TEXTMODE_SCREEN_BUFFER ?? **/ - PWCHAR LineBuffer; /* Current line being input, in line buffered mode */ - WORD LineMaxSize; /* Maximum size of line in characters (including CR+LF) */ - WORD LineSize; /* Current size of line */ - WORD LinePos; /* Current position within line */ + /** Put those things in CONSOLE_INPUT_BUFFER ?? **/ + PWCHAR LineBuffer; /* Current line being input, in line buffered mode */ + ULONG LineMaxSize; /* Maximum size of line in characters (including CR+LF) */ + ULONG LineSize; /* Current size of line */ + ULONG LinePos; /* Current position within line */ BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */ BOOLEAN LineUpPressed; BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */ - ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */ - /***************************************************/ + ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */ + /*************************************************/ - BOOLEAN QuickEdit; BOOLEAN InsertMode; - UINT CodePage; /******************************* Screen buffers *******************************/ LIST_ENTRY BufferList; /* List of all screen buffers for this console */ PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ - BYTE PauseFlags; - HANDLE UnpauseEvent; - LIST_ENTRY WriteWaitQueue; /* List head for the queue of write wait blocks */ UINT OutputCodePage; -/**************************** Aliases and Histories ***************************/ - struct _ALIAS_HEADER *Aliases; - LIST_ENTRY HistoryBuffers; - ULONG HistoryBufferSize; /* Size for newly created history buffers */ - ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */ - BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */ - /****************************** Other properties ******************************/ UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */ UNICODE_STRING Title; /* Title of console. Always NULL-terminated */ + HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */ + COORD ConsoleSize; /* The current size of the console, for text-mode only */ BOOLEAN FixedSize; /* TRUE if the console is of fixed size */ COLORREF Colors[16]; /* Colour palette */ -} CONSOLE, *PCONSOLE; +} CONSOLE; // , *PCONSOLE; -/* PauseFlags values (internal only) */ -#define PAUSED_FROM_KEYBOARD 0x1 -#define PAUSED_FROM_SCROLLBAR 0x2 -#define PAUSED_FROM_SELECTION 0x4 +// #include "conio_winsrv.h" /* console.c */ -VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags); -VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags); +VOID NTAPI +ConDrvPause(PCONSOLE Console); +VOID NTAPI +ConDrvUnpause(PCONSOLE Console); PCONSOLE_PROCESS_DATA NTAPI -ConDrvGetConsoleLeaderProcess(IN PCONSOLE Console); +ConSrvGetConsoleLeaderProcess(IN PCONSOLE Console); NTSTATUS -ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent, +ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent, IN PCONSOLE_PROCESS_DATA ProcessData); NTSTATUS NTAPI -ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console, +ConSrvConsoleProcessCtrlEvent(IN PCONSOLE Console, IN ULONG ProcessGroupId, IN ULONG CtrlEvent); /* coninput.c */ VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg); -NTSTATUS FASTCALL ConioAddInputEvent(PCONSOLE Console, - PINPUT_RECORD InputEvent, - BOOLEAN AppendToEnd); -NTSTATUS FASTCALL ConioProcessInputEvent(PCONSOLE Console, - PINPUT_RECORD InputEvent); +NTSTATUS +ConioAddInputEvents(PCONSOLE Console, + PINPUT_RECORD InputRecords, + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd); +NTSTATUS +ConioProcessInputEvent(PCONSOLE Console, + PINPUT_RECORD InputEvent); /* conoutput.c */ -#define ConioInitRect(Rect, top, left, bottom, right) \ -do { \ - ((Rect)->Top) = top; \ - ((Rect)->Left) = left; \ - ((Rect)->Bottom) = bottom; \ - ((Rect)->Right) = right; \ -} while (0) -#define ConioIsRectEmpty(Rect) \ - (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) -#define ConioRectHeight(Rect) \ - (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) -#define ConioRectWidth(Rect) \ - (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y); -VOID FASTCALL ConioDrawConsole(PCONSOLE Console); +VOID ConioDrawConsole(PCONSOLE Console); NTSTATUS ConioResizeBuffer(PCONSOLE Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, COORD Size); @@ -391,7 +369,7 @@ NTSTATUS ConioWriteConsole(PCONSOLE Console, PWCHAR Buffer, DWORD Length, BOOL Attrib); -DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, +DWORD ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale); /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h b/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h new file mode 100644 index 00000000000..aba4715a2b8 --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h @@ -0,0 +1,185 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: consrv/include/conio_winsrv.h + * PURPOSE: Public Console I/O Interface + * PROGRAMMERS: Gé van Geldorp + * Jeffrey Morlan + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#pragma once + +#include "rect.h" + +#define CSR_DEFAULT_CURSOR_SIZE 25 + +typedef struct _FRONTEND FRONTEND, *PFRONTEND; +/* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO; +typedef struct _FRONTEND_VTBL +{ + // NTSTATUS (NTAPI *UnloadFrontEnd)(IN OUT PFRONTEND This); + + /* + * Internal interface (functions called by the console server only) + */ + NTSTATUS (NTAPI *InitFrontEnd)(IN OUT PFRONTEND This, + IN struct _CONSOLE* Console); + VOID (NTAPI *DeinitFrontEnd)(IN OUT PFRONTEND This); + + /* Interface used for both text-mode and graphics screen buffers */ + VOID (NTAPI *DrawRegion)(IN OUT PFRONTEND This, + SMALL_RECT* Region); + /* Interface used only for text-mode screen buffers */ + VOID (NTAPI *WriteStream)(IN OUT PFRONTEND This, + SMALL_RECT* Region, + SHORT CursorStartX, + SHORT CursorStartY, + UINT ScrolledLines, + PWCHAR Buffer, + UINT Length); + BOOL (NTAPI *SetCursorInfo)(IN OUT PFRONTEND This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer); + BOOL (NTAPI *SetScreenInfo)(IN OUT PFRONTEND This, + PCONSOLE_SCREEN_BUFFER ScreenBuffer, + SHORT OldCursorX, + SHORT OldCursorY); + VOID (NTAPI *ResizeTerminal)(IN OUT PFRONTEND This); + VOID (NTAPI *SetActiveScreenBuffer)(IN OUT PFRONTEND This); + VOID (NTAPI *ReleaseScreenBuffer)(IN OUT PFRONTEND This, + IN PCONSOLE_SCREEN_BUFFER ScreenBuffer); + VOID (NTAPI *RefreshInternalInfo)(IN OUT PFRONTEND This); + + /* + * External interface (functions corresponding to the Console API) + */ + VOID (NTAPI *ChangeTitle)(IN OUT PFRONTEND This); + BOOL (NTAPI *ChangeIcon)(IN OUT PFRONTEND This, + HICON IconHandle); + HWND (NTAPI *GetConsoleWindowHandle)(IN OUT PFRONTEND This); + VOID (NTAPI *GetLargestConsoleWindowSize)(IN OUT PFRONTEND This, + PCOORD pSize); + BOOL (NTAPI *GetSelectionInfo)(IN OUT PFRONTEND This, + PCONSOLE_SELECTION_INFO pSelectionInfo); + BOOL (NTAPI *SetPalette)(IN OUT PFRONTEND This, + HPALETTE PaletteHandle, + UINT PaletteUsage); + ULONG (NTAPI *GetDisplayMode)(IN OUT PFRONTEND This); + BOOL (NTAPI *SetDisplayMode)(IN OUT PFRONTEND This, + ULONG NewMode); + INT (NTAPI *ShowMouseCursor)(IN OUT PFRONTEND This, + BOOL Show); + BOOL (NTAPI *SetMouseCursor)(IN OUT PFRONTEND This, + HCURSOR CursorHandle); + HMENU (NTAPI *MenuControl)(IN OUT PFRONTEND This, + UINT CmdIdLow, + UINT CmdIdHigh); + BOOL (NTAPI *SetMenuClose)(IN OUT PFRONTEND This, + BOOL Enable); +} FRONTEND_VTBL, *PFRONTEND_VTBL; + +struct _FRONTEND +{ + PFRONTEND_VTBL Vtbl; /* Virtual table */ + NTSTATUS (NTAPI *UnloadFrontEnd)(IN OUT PFRONTEND This); + + struct _CONSOLE* Console; /* Console to which the frontend is attached to */ + PVOID Data; /* Private data */ + PVOID OldData; /* Reserved */ +}; + +/* PauseFlags values (internal only) */ +#define PAUSED_FROM_KEYBOARD 0x1 +#define PAUSED_FROM_SCROLLBAR 0x2 +#define PAUSED_FROM_SELECTION 0x4 + +typedef struct _WINSRV_CONSOLE +{ +/******************************* Console Set-up *******************************/ + /* This **MUST** be FIRST!! */ + // CONSOLE; + + // LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */ + // CRITICAL_SECTION Lock; + // CONSOLE_STATE State; /* State of the console */ + + FRONTEND FrontEndIFace; /* Frontend-specific interface */ + +/******************************* Process support ******************************/ + LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */ + PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that needs to be notified when the console leader process is killed */ + BOOLEAN NotifyLastClose; /* TRUE if the console should send a control event when the console leader process is killed */ + + BOOLEAN QuickEdit; + +/******************************* Pausing support ******************************/ + BYTE PauseFlags; + LIST_ENTRY ReadWaitQueue; /* List head for the queue of unique input buffer read wait blocks */ + LIST_ENTRY WriteWaitQueue; /* List head for the queue of current screen-buffer write wait blocks */ + +/**************************** Aliases and Histories ***************************/ + struct _ALIAS_HEADER *Aliases; + LIST_ENTRY HistoryBuffers; + ULONG HistoryBufferSize; /* Size for newly created history buffers */ + ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */ + BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */ + +} WINSRV_CONSOLE, *PWINSRV_CONSOLE; + +/* console.c */ +VOID ConioPause(PCONSOLE Console, UINT Flags); +VOID ConioUnpause(PCONSOLE Console, UINT Flags); + +PCONSOLE_PROCESS_DATA NTAPI +ConSrvGetConsoleLeaderProcess(IN PCONSOLE Console); +NTSTATUS +ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent, + IN PCONSOLE_PROCESS_DATA ProcessData); +NTSTATUS NTAPI +ConSrvConsoleProcessCtrlEvent(IN PCONSOLE Console, + IN ULONG ProcessGroupId, + IN ULONG CtrlEvent); + +/* coninput.c */ +VOID NTAPI ConioProcessKey(PCONSOLE Console, MSG* msg); +DWORD ConioEffectiveCursorSize(PCONSOLE Console, + DWORD Scale); + +NTSTATUS +ConioAddInputEvents(PCONSOLE Console, + PINPUT_RECORD InputRecords, + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd); +NTSTATUS +ConioProcessInputEvent(PCONSOLE Console, + PINPUT_RECORD InputEvent); + +/* conoutput.c */ + +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ +#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + +#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) + +PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y); +VOID ConioDrawConsole(PCONSOLE Console); +NTSTATUS ConioResizeBuffer(PCONSOLE Console, + PTEXTMODE_SCREEN_BUFFER ScreenBuffer, + COORD Size); +NTSTATUS ConioWriteConsole(PCONSOLE Console, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib); + +/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/include/console.h b/reactos/win32ss/user/winsrv/consrv/include/console.h index 4214e071e18..120663224da 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/console.h +++ b/reactos/win32ss/user/winsrv/consrv/include/console.h @@ -12,15 +12,13 @@ VOID NTAPI ConDrvInitConsoleSupport(VOID); NTSTATUS NTAPI -ConDrvInitConsole(OUT PHANDLE NewConsoleHandle, - OUT PCONSOLE* NewConsole, - IN PCONSOLE_INFO ConsoleInfo, - IN ULONG ConsoleLeaderProcessId); +ConDrvInitConsole(OUT PCONSOLE* NewConsole, + IN PCONSOLE_INFO ConsoleInfo); NTSTATUS NTAPI -ConDrvRegisterFrontEnd(IN PCONSOLE Console, - IN PFRONTEND FrontEnd); +ConDrvRegisterTerminal(IN PCONSOLE Console, + IN PTERMINAL Terminal); NTSTATUS NTAPI -ConDrvDeregisterFrontEnd(IN PCONSOLE Console); +ConDrvDeregisterTerminal(IN PCONSOLE Console); VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console); @@ -35,20 +33,4 @@ ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole); -BOOLEAN NTAPI -ConDrvValidateConsole(OUT PCONSOLE* Console, - IN HANDLE ConsoleHandle, - IN CONSOLE_STATE ExpectedState, - IN BOOLEAN LockConsole); - - - -NTSTATUS NTAPI -ConDrvGetConsole(OUT PCONSOLE* Console, - IN HANDLE ConsoleHandle, - IN BOOLEAN LockConsole); -VOID NTAPI -ConDrvReleaseConsole(IN PCONSOLE Console, - IN BOOLEAN WasConsoleLocked); - /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/include/rect.h b/reactos/win32ss/user/winsrv/consrv/include/rect.h new file mode 100644 index 00000000000..8a78d90265c --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/include/rect.h @@ -0,0 +1,85 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: consrv/include/rect.h + * PURPOSE: Rectangle helper functions + * PROGRAMMERS: Gé van Geldorp + * Jeffrey Morlan + */ + +#pragma once + +#define ConioInitRect(Rect, top, left, bottom, right) \ +do { \ + ((Rect)->Top) = top; \ + ((Rect)->Left) = left; \ + ((Rect)->Bottom) = bottom; \ + ((Rect)->Right) = right; \ +} while (0) +#define ConioIsRectEmpty(Rect) \ + (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) + +#define ConioRectHeight(Rect) \ + (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) +#define ConioRectWidth(Rect) \ + (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) + + +static __inline BOOLEAN +ConioGetIntersection(OUT PSMALL_RECT Intersection, + IN PSMALL_RECT Rect1, + IN PSMALL_RECT Rect2) +{ + if ( ConioIsRectEmpty(Rect1) || + ConioIsRectEmpty(Rect2) || + (Rect1->Top > Rect2->Bottom) || + (Rect1->Left > Rect2->Right) || + (Rect1->Bottom < Rect2->Top) || + (Rect1->Right < Rect2->Left) ) + { + /* The rectangles do not intersect */ + ConioInitRect(Intersection, 0, -1, 0, -1); + return FALSE; + } + + ConioInitRect(Intersection, + max(Rect1->Top , Rect2->Top ), + max(Rect1->Left , Rect2->Left ), + min(Rect1->Bottom, Rect2->Bottom), + min(Rect1->Right , Rect2->Right )); + + return TRUE; +} + +static __inline BOOLEAN +ConioGetUnion(OUT PSMALL_RECT Union, + IN PSMALL_RECT Rect1, + IN PSMALL_RECT Rect2) +{ + if (ConioIsRectEmpty(Rect1)) + { + if (ConioIsRectEmpty(Rect2)) + { + ConioInitRect(Union, 0, -1, 0, -1); + return FALSE; + } + else + { + *Union = *Rect2; + } + } + else if (ConioIsRectEmpty(Rect2)) + { + *Union = *Rect1; + } + else + { + ConioInitRect(Union, + min(Rect1->Top , Rect2->Top ), + min(Rect1->Left , Rect2->Left ), + max(Rect1->Bottom, Rect2->Bottom), + max(Rect1->Right , Rect2->Right )); + } + + return TRUE; +} diff --git a/reactos/win32ss/user/winsrv/consrv/include/term.h b/reactos/win32ss/user/winsrv/consrv/include/term.h index b8cc5523e2f..037f6e8c314 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/term.h +++ b/reactos/win32ss/user/winsrv/consrv/include/term.h @@ -12,8 +12,8 @@ #define TermDrawRegion(Console, Region) \ (Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region)) -#define TermWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ - (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Block), (CurStartX), (CurStartY), \ +#define TermWriteStream(Console, Region, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ + (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Region), (CurStartX), (CurStartY), \ (ScrolledLines), (Buffer), (Length)) #define TermSetCursorInfo(Console, ScreenBuffer) \ (Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (ScreenBuffer)) @@ -25,34 +25,32 @@ (Console)->TermIFace.Vtbl->SetActiveScreenBuffer(&(Console)->TermIFace) #define TermReleaseScreenBuffer(Console, ScreenBuffer) \ (Console)->TermIFace.Vtbl->ReleaseScreenBuffer(&(Console)->TermIFace, (ScreenBuffer)) -#define TermProcessKeyCallback(Console, Msg, KeyStateMenu, ShiftState, VirtualKeyCode, Down) \ - (Console)->TermIFace.Vtbl->ProcessKeyCallback(&(Console)->TermIFace, (Msg), (KeyStateMenu), (ShiftState), (VirtualKeyCode), (Down)) #define TermRefreshInternalInfo(Console) \ - (Console)->TermIFace.Vtbl->RefreshInternalInfo(&(Console)->TermIFace) + (Console)->FrontEndIFace.Vtbl->RefreshInternalInfo(&(Console)->FrontEndIFace) #define TermChangeTitle(Console) \ (Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace) #define TermChangeIcon(Console, IconHandle) \ - (Console)->TermIFace.Vtbl->ChangeIcon(&(Console)->TermIFace, (IconHandle)) + (Console)->FrontEndIFace.Vtbl->ChangeIcon(&(Console)->FrontEndIFace, (IconHandle)) #define TermGetConsoleWindowHandle(Console) \ - (Console)->TermIFace.Vtbl->GetConsoleWindowHandle(&(Console)->TermIFace) + (Console)->FrontEndIFace.Vtbl->GetConsoleWindowHandle(&(Console)->FrontEndIFace) #define TermGetLargestConsoleWindowSize(Console, pSize) \ (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize)) #define TermGetSelectionInfo(Console, pSelectionInfo) \ - (Console)->TermIFace.Vtbl->GetSelectionInfo(&(Console)->TermIFace, (pSelectionInfo)) + (Console)->FrontEndIFace.Vtbl->GetSelectionInfo(&(Console)->FrontEndIFace, (pSelectionInfo)) #define TermSetPalette(Console, PaletteHandle, PaletteUsage) \ (Console)->TermIFace.Vtbl->SetPalette(&(Console)->TermIFace, (PaletteHandle), (PaletteUsage)) #define TermGetDisplayMode(Console) \ - (Console)->TermIFace.Vtbl->GetDisplayMode(&(Console)->TermIFace) + (Console)->FrontEndIFace.Vtbl->GetDisplayMode(&(Console)->FrontEndIFace) #define TermSetDisplayMode(Console, NewMode) \ - (Console)->TermIFace.Vtbl->SetDisplayMode(&(Console)->TermIFace, (NewMode)) + (Console)->FrontEndIFace.Vtbl->SetDisplayMode(&(Console)->FrontEndIFace, (NewMode)) #define TermShowMouseCursor(Console, Show) \ (Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show)) #define TermSetMouseCursor(Console, CursorHandle) \ - (Console)->TermIFace.Vtbl->SetMouseCursor(&(Console)->TermIFace, (CursorHandle)) + (Console)->FrontEndIFace.Vtbl->SetMouseCursor(&(Console)->FrontEndIFace, (CursorHandle)) #define TermMenuControl(Console, CmdIdLow, CmdIdHigh) \ - (Console)->TermIFace.Vtbl->MenuControl(&(Console)->TermIFace, (CmdIdLow), (CmdIdHigh)) + (Console)->FrontEndIFace.Vtbl->MenuControl(&(Console)->FrontEndIFace, (CmdIdLow), (CmdIdHigh)) #define TermSetMenuClose(Console, Enable) \ - (Console)->TermIFace.Vtbl->SetMenuClose(&(Console)->TermIFace, (Enable)) + (Console)->FrontEndIFace.Vtbl->SetMenuClose(&(Console)->FrontEndIFace, (Enable)) /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/init.c b/reactos/win32ss/user/winsrv/consrv/init.c index c669c52d46a..3f50c6b1ba9 100644 --- a/reactos/win32ss/user/winsrv/consrv/init.c +++ b/reactos/win32ss/user/winsrv/consrv/init.c @@ -353,7 +353,7 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, /* Initialize the new (target) process */ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData)); TargetProcessData->Process = TargetProcess; - TargetProcessData->ConsoleEvent = NULL; + TargetProcessData->InputWaitHandle = NULL; TargetProcessData->ConsoleHandle = TargetProcessData->ParentConsoleHandle = NULL; TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE); @@ -383,7 +383,7 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, PCONSOLE SourceConsole; /* Validate and lock the parent's console */ - if (ConDrvValidateConsole(&SourceConsole, + if (ConSrvValidateConsole(&SourceConsole, SourceProcessData->ConsoleHandle, CONSOLE_RUNNING, TRUE)) { @@ -484,7 +484,7 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, /* Return the console handle and the input wait handle to the caller */ ConnectInfo->ConsoleHandle = ProcessData->ConsoleHandle; - ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent; + ConnectInfo->InputWaitHandle = ProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ ProcessData->PropDispatcher = ConnectInfo->ConsoleStartInfo.PropDispatcher; @@ -529,6 +529,7 @@ CSR_SERVER_DLL_INIT(ConServerDllInitialization) */ ConDrvInitConsoleSupport(); + ConSrvInitConsoleSupport(); /* Setup the DLL Object */ LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER; diff --git a/reactos/win32ss/user/winsrv/consrv/lineinput.c b/reactos/win32ss/user/winsrv/consrv/lineinput.c index a9ffc8dd191..c3ae65e6edb 100644 --- a/reactos/win32ss/user/winsrv/consrv/lineinput.c +++ b/reactos/win32ss/user/winsrv/consrv/lineinput.c @@ -4,8 +4,6 @@ * FILE: win32ss/user/winsrv/consrv/lineinput.c * PURPOSE: Console line input functions * PROGRAMMERS: Jeffrey Morlan - * - * NOTE: It's something frontend-related... (--> read my mind... ;) ) */ /* INCLUDES *******************************************************************/ @@ -21,30 +19,45 @@ typedef struct _HISTORY_BUFFER UINT Position; UINT MaxEntries; UINT NumEntries; - PUNICODE_STRING Entries; UNICODE_STRING ExeName; + PUNICODE_STRING Entries; } HISTORY_BUFFER, *PHISTORY_BUFFER; +BOOLEAN +ConvertInputAnsiToUnicode(PCONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsUnicode, + PWCHAR* Target, + PUSHORT TargetLength); +BOOLEAN +ConvertInputUnicodeToAnsi(PCONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsAnsi, + PCHAR/* * */ Target, + /*P*/USHORT TargetLength); + + /* PRIVATE FUNCTIONS **********************************************************/ static PHISTORY_BUFFER -HistoryCurrentBuffer(PCONSOLE Console) +HistoryCurrentBuffer(PCONSOLE Console, + PUNICODE_STRING ExeName) { - /* TODO: use actual EXE name sent from process that called ReadConsole */ - UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" }; PLIST_ENTRY Entry = Console->HistoryBuffers.Flink; PHISTORY_BUFFER Hist; for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink) { Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); - if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE)) + if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE)) return Hist; } /* Couldn't find the buffer, create a new one */ - Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName.Length); + Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length); if (!Hist) return NULL; Hist->MaxEntries = Console->HistoryBufferSize; Hist->NumEntries = 0; @@ -54,18 +67,19 @@ HistoryCurrentBuffer(PCONSOLE Console) ConsoleFreeHeap(Hist); return NULL; } - Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length; + Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length; Hist->ExeName.Buffer = (PWCHAR)(Hist + 1); - memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length); + memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length); InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry); return Hist; } static VOID -HistoryAddEntry(PCONSOLE Console) +HistoryAddEntry(PCONSOLE Console, + PUNICODE_STRING ExeName) { UNICODE_STRING NewEntry; - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console); + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); INT i; if (!Hist) return; @@ -113,9 +127,11 @@ HistoryAddEntry(PCONSOLE Console) } static VOID -HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry) +HistoryGetCurrentEntry(PCONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Entry) { - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console); + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); if (!Hist || Hist->NumEntries == 0) Entry->Length = 0; @@ -124,17 +140,51 @@ HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry) } static PHISTORY_BUFFER -HistoryFindBuffer(PCONSOLE Console, PUNICODE_STRING ExeName) +HistoryFindBuffer(PCONSOLE Console, + PVOID ExeName, + USHORT ExeLength, + BOOLEAN UnicodeExe) { - PLIST_ENTRY Entry = Console->HistoryBuffers.Flink; + UNICODE_STRING ExeNameU; + + PLIST_ENTRY Entry; + PHISTORY_BUFFER Hist = NULL; + + if (ExeName == NULL) return NULL; + + if (UnicodeExe) + { + ExeNameU.Buffer = ExeName; + /* Length is in bytes */ + ExeNameU.MaximumLength = ExeLength; + } + else + { + if (!ConvertInputAnsiToUnicode(Console, + ExeName, ExeLength, + &ExeNameU.Buffer, &ExeNameU.MaximumLength)) + { + return NULL; + } + } + ExeNameU.Length = ExeNameU.MaximumLength; + + Entry = Console->HistoryBuffers.Flink; while (Entry != &Console->HistoryBuffers) { + Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); + /* For the history APIs, the caller is allowed to give only part of the name */ - PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); - if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE)) + if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE)) + { + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); return Hist; + } + Entry = Entry->Flink; } + + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); return NULL; } @@ -151,7 +201,7 @@ HistoryDeleteBuffer(PHISTORY_BUFFER Hist) ConsoleFreeHeap(Hist); } -VOID FASTCALL +VOID HistoryDeleteBuffers(PCONSOLE Console) { PLIST_ENTRY CurrentEntry; @@ -190,7 +240,7 @@ LineInputSetPos(PCONSOLE Console, UINT Pos) } static VOID -LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion) +LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Insertion) { PTEXTMODE_SCREEN_BUFFER ActiveBuffer; UINT Pos = Console->LinePos; @@ -227,9 +277,11 @@ LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Inser } static VOID -LineInputRecallHistory(PCONSOLE Console, INT Offset) +LineInputRecallHistory(PCONSOLE Console, + PUNICODE_STRING ExeName, + INT Offset) { - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console); + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); UINT Position = 0; if (!Hist || Hist->NumEntries == 0) return; @@ -244,8 +296,10 @@ LineInputRecallHistory(PCONSOLE Console, INT Offset) Hist->Entries[Hist->Position].Buffer); } -VOID FASTCALL -LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) +VOID +LineInputKeyDown(PCONSOLE Console, + PUNICODE_STRING ExeName, + KEY_EVENT_RECORD *KeyEvent) { UINT Pos = Console->LinePos; PHISTORY_BUFFER Hist; @@ -298,7 +352,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) else { /* Recall one character (but don't overwrite current line) */ - HistoryGetCurrentEntry(Console, &Entry); + HistoryGetCurrentEntry(Console, ExeName, &Entry); if (Pos < Console->LineSize) LineInputSetPos(Console, Pos + 1); else if (Pos * sizeof(WCHAR) < Entry.Length) @@ -317,26 +371,26 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) return; case VK_PRIOR: /* Recall first history entry */ - LineInputRecallHistory(Console, -((WORD)-1)); + LineInputRecallHistory(Console, ExeName, -((WORD)-1)); return; case VK_NEXT: /* Recall last history entry */ - LineInputRecallHistory(Console, +((WORD)-1)); + LineInputRecallHistory(Console, ExeName, +((WORD)-1)); return; case VK_UP: case VK_F5: /* Recall previous history entry. On first time, actually recall the * current (usually last) entry; on subsequent times go back. */ - LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0); + LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0); Console->LineUpPressed = TRUE; return; case VK_DOWN: /* Recall next history entry */ - LineInputRecallHistory(Console, +1); + LineInputRecallHistory(Console, ExeName, +1); return; case VK_F3: /* Recall remainder of current history entry */ - HistoryGetCurrentEntry(Console, &Entry); + HistoryGetCurrentEntry(Console, ExeName, &Entry); if (Pos * sizeof(WCHAR) < Entry.Length) { UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos); @@ -350,11 +404,11 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) break; case VK_F7: if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - HistoryDeleteBuffer(HistoryCurrentBuffer(Console)); + HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName)); return; case VK_F8: /* Search for history entries starting with input. */ - Hist = HistoryCurrentBuffer(Console); + Hist = HistoryCurrentBuffer(Console, ExeName); if (!Hist || Hist->NumEntries == 0) return; /* Like Up/F5, on first time start from current (usually last) entry, @@ -398,7 +452,7 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) } else if (KeyEvent->uChar.UnicodeChar == L'\r') { - HistoryAddEntry(Console); + HistoryAddEntry(Console, ExeName); /* TODO: Expand aliases */ @@ -455,163 +509,216 @@ LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent) CSR_API(SrvGetConsoleCommandHistory) { - PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest; - PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); - PCONSOLE Console; NTSTATUS Status; + PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest; + PCONSOLE Console; + ULONG BytesWritten = 0; PHISTORY_BUFFER Hist; - PBYTE Buffer = (PBYTE)GetCommandHistoryRequest->History; - ULONG BufferSize = GetCommandHistoryRequest->Length; - UINT i; + + DPRINT1("SrvGetConsoleCommandHistory entered\n"); if ( !CsrValidateMessageBuffer(ApiMessage, (PVOID*)&GetCommandHistoryRequest->History, - GetCommandHistoryRequest->Length, + GetCommandHistoryRequest->HistoryLength, sizeof(BYTE)) || !CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetCommandHistoryRequest->ExeName.Buffer, - GetCommandHistoryRequest->ExeName.Length, + (PVOID*)&GetCommandHistoryRequest->ExeName, + GetCommandHistoryRequest->ExeLength, sizeof(BYTE)) ) { return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ProcessData, &Console, TRUE); - if (NT_SUCCESS(Status)) + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + GetCommandHistoryRequest->ExeName, + GetCommandHistoryRequest->ExeLength, + GetCommandHistoryRequest->Unicode2); + if (Hist) { - Hist = HistoryFindBuffer(Console, &GetCommandHistoryRequest->ExeName); - if (Hist) + UINT i; + + LPSTR TargetBufferA; + LPWSTR TargetBufferW; + ULONG BufferSize = GetCommandHistoryRequest->HistoryLength; + + UINT Offset = 0; + UINT SourceLength; + + if (GetCommandHistoryRequest->Unicode) { - for (i = 0; i < Hist->NumEntries; i++) + TargetBufferW = GetCommandHistoryRequest->History; + BufferSize /= sizeof(WCHAR); + } + else + { + TargetBufferA = GetCommandHistoryRequest->History; + } + + for (i = 0; i < Hist->NumEntries; i++) + { + SourceLength = Hist->Entries[i].Length / sizeof(WCHAR); + if (Offset + SourceLength + 1 > BufferSize) { - if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR))) - { - Status = STATUS_BUFFER_OVERFLOW; - break; - } - memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length); - Buffer += Hist->Entries[i].Length; - *(PWCHAR)Buffer = L'\0'; - Buffer += sizeof(WCHAR); + Status = STATUS_BUFFER_OVERFLOW; + break; + } + + if (GetCommandHistoryRequest->Unicode) + { + RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR)); + Offset += SourceLength; + TargetBufferW[Offset++] = L'\0'; + } + else + { + ConvertInputUnicodeToAnsi(Console, + Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR), + &TargetBufferA[Offset], SourceLength); + Offset += SourceLength; + TargetBufferA[Offset++] = '\0'; } } - GetCommandHistoryRequest->Length = Buffer - (PBYTE)GetCommandHistoryRequest->History; - ConSrvReleaseConsole(Console, TRUE); + + if (GetCommandHistoryRequest->Unicode) + BytesWritten = Offset * sizeof(WCHAR); + else + BytesWritten = Offset; } + + // GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History; + GetCommandHistoryRequest->HistoryLength = BytesWritten; + + ConSrvReleaseConsole(Console, TRUE); return Status; } CSR_API(SrvGetConsoleCommandHistoryLength) { - PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest; - PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); - PCONSOLE Console; NTSTATUS Status; + PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest; + PCONSOLE Console; PHISTORY_BUFFER Hist; ULONG Length = 0; UINT i; if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetCommandHistoryLengthRequest->ExeName.Buffer, - GetCommandHistoryLengthRequest->ExeName.Length, + (PVOID*)&GetCommandHistoryLengthRequest->ExeName, + GetCommandHistoryLengthRequest->ExeLength, sizeof(BYTE))) { return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ProcessData, &Console, TRUE); - if (NT_SUCCESS(Status)) + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + GetCommandHistoryLengthRequest->ExeName, + GetCommandHistoryLengthRequest->ExeLength, + GetCommandHistoryLengthRequest->Unicode2); + if (Hist) { - Hist = HistoryFindBuffer(Console, &GetCommandHistoryLengthRequest->ExeName); - if (Hist) - { - for (i = 0; i < Hist->NumEntries; i++) - Length += Hist->Entries[i].Length + sizeof(WCHAR); - } - GetCommandHistoryLengthRequest->Length = Length; - ConSrvReleaseConsole(Console, TRUE); + for (i = 0; i < Hist->NumEntries; i++) + Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated } + /* + * Quick and dirty way of getting the number of bytes of the + * corresponding ANSI string from the one in UNICODE. + */ + if (!GetCommandHistoryLengthRequest->Unicode) + Length /= sizeof(WCHAR); + + GetCommandHistoryLengthRequest->HistoryLength = Length; + + ConSrvReleaseConsole(Console, TRUE); return Status; } CSR_API(SrvExpungeConsoleCommandHistory) { + NTSTATUS Status; PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest; - PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCONSOLE Console; PHISTORY_BUFFER Hist; - NTSTATUS Status; if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ExpungeCommandHistoryRequest->ExeName.Buffer, - ExpungeCommandHistoryRequest->ExeName.Length, + (PVOID*)&ExpungeCommandHistoryRequest->ExeName, + ExpungeCommandHistoryRequest->ExeLength, sizeof(BYTE))) { return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ProcessData, &Console, TRUE); - if (NT_SUCCESS(Status)) - { - Hist = HistoryFindBuffer(Console, &ExpungeCommandHistoryRequest->ExeName); - HistoryDeleteBuffer(Hist); - ConSrvReleaseConsole(Console, TRUE); - } + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + ExpungeCommandHistoryRequest->ExeName, + ExpungeCommandHistoryRequest->ExeLength, + ExpungeCommandHistoryRequest->Unicode2); + HistoryDeleteBuffer(Hist); + + ConSrvReleaseConsole(Console, TRUE); return Status; } CSR_API(SrvSetConsoleNumberOfCommands) { + NTSTATUS Status; PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest; - PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCONSOLE Console; PHISTORY_BUFFER Hist; - NTSTATUS Status; - UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands; - PUNICODE_STRING OldEntryList, NewEntryList; if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&SetHistoryNumberCommandsRequest->ExeName.Buffer, - SetHistoryNumberCommandsRequest->ExeName.Length, + (PVOID*)&SetHistoryNumberCommandsRequest->ExeName, + SetHistoryNumberCommandsRequest->ExeLength, sizeof(BYTE))) { return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ProcessData, &Console, TRUE); - if (NT_SUCCESS(Status)) - { - Hist = HistoryFindBuffer(Console, &SetHistoryNumberCommandsRequest->ExeName); - if (Hist) - { - OldEntryList = Hist->Entries; - NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING)); - if (!NewEntryList) - { - Status = STATUS_NO_MEMORY; - } - else - { - /* If necessary, shrink by removing oldest entries */ - for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--) - { - RtlFreeUnicodeString(Hist->Entries++); - Hist->Position += (Hist->Position == 0); - } + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; - Hist->MaxEntries = MaxEntries; - Hist->Entries = memcpy(NewEntryList, Hist->Entries, - Hist->NumEntries * sizeof(UNICODE_STRING)); - ConsoleFreeHeap(OldEntryList); - } + Hist = HistoryFindBuffer(Console, + SetHistoryNumberCommandsRequest->ExeName, + SetHistoryNumberCommandsRequest->ExeLength, + SetHistoryNumberCommandsRequest->Unicode2); + if (Hist) + { + UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands; + PUNICODE_STRING OldEntryList = Hist->Entries; + PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING)); + if (!NewEntryList) + { + Status = STATUS_NO_MEMORY; + } + else + { + /* If necessary, shrink by removing oldest entries */ + for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--) + { + RtlFreeUnicodeString(Hist->Entries++); + Hist->Position += (Hist->Position == 0); + } + + Hist->MaxEntries = MaxEntries; + Hist->Entries = memcpy(NewEntryList, Hist->Entries, + Hist->NumEntries * sizeof(UNICODE_STRING)); + ConsoleFreeHeap(OldEntryList); } - ConSrvReleaseConsole(Console, TRUE); } + + ConSrvReleaseConsole(Console, TRUE); return Status; } CSR_API(SrvGetConsoleHistory) { +#if 0 // Vista+ PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; PCONSOLE Console; NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); @@ -623,10 +730,15 @@ CSR_API(SrvGetConsoleHistory) ConSrvReleaseConsole(Console, TRUE); } return Status; +#else + DPRINT1("%s not yet implemented\n", __FUNCTION__); + return STATUS_NOT_IMPLEMENTED; +#endif } CSR_API(SrvSetConsoleHistory) { +#if 0 // Vista+ PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; PCONSOLE Console; NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); @@ -638,12 +750,29 @@ CSR_API(SrvSetConsoleHistory) ConSrvReleaseConsole(Console, TRUE); } return Status; +#else + DPRINT1("%s not yet implemented\n", __FUNCTION__); + return STATUS_NOT_IMPLEMENTED; +#endif } CSR_API(SrvSetConsoleCommandHistoryMode) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest; + PCONSOLE Console; + + DPRINT1("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n", + SetHistoryModeRequest->Mode); + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + /* This API is not yet implemented */ + Status = STATUS_NOT_IMPLEMENTED; + + ConSrvReleaseConsole(Console, TRUE); + return Status; } /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/lineinput.h b/reactos/win32ss/user/winsrv/consrv/lineinput.h index b2531418d4f..afb6d25f216 100644 --- a/reactos/win32ss/user/winsrv/consrv/lineinput.h +++ b/reactos/win32ss/user/winsrv/consrv/lineinput.h @@ -8,5 +8,9 @@ #pragma once -VOID FASTCALL HistoryDeleteBuffers(PCONSOLE Console); -VOID FASTCALL LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent); +VOID HistoryDeleteBuffers(PCONSOLE Console); + +VOID +LineInputKeyDown(PCONSOLE Console, + PUNICODE_STRING ExeName, + KEY_EVENT_RECORD *KeyEvent); diff --git a/reactos/win32ss/user/winsrv/consrv/procinit.h b/reactos/win32ss/user/winsrv/consrv/procinit.h index ec36c8ca038..9c7186667dd 100644 --- a/reactos/win32ss/user/winsrv/consrv/procinit.h +++ b/reactos/win32ss/user/winsrv/consrv/procinit.h @@ -8,15 +8,15 @@ #pragma once -NTSTATUS FASTCALL ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, +NTSTATUS ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, PCONSOLE_START_INFO ConsoleStartInfo); -NTSTATUS FASTCALL ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, +NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, HANDLE ConsoleHandle, BOOL CreateNewHandlesTable, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle); -VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData); +VOID ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);