mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 08:13:01 +00:00
[KERNEL32/CONSRV]
- Move the waiting loop of IntReadConsole into SrvReadConsole instead. - Merge IntPeekConsoleInput and IntReadConsoleInput helpers into a single IntGetConsoleInput helper function and make PeekConsoleInputW/A and ReadConsoleInputW/A use it. Indeed, the "only" difference between these two functions, is that the first one keeps the data read inside the console input buffer, but on the contrary the second removes the data and does not return until at least one input record has been read. In server-side, CsrReadInputEvent and CsrPeekConsoleInput are merged into SrvGetConsoleInput. Merge the corresponding structures. - Use shorter variable names in IntReadConsoleOutput and use CONSOLE_PROCESS_DATA structure in SrvReadConsoleOutput. - Merge IntReadConsoleOutputCharacter and ReadConsoleOutputAttribute functions into a single IntReadConsoleOutputCode helper function, and make ReadConsoleOutputAttribute and ReadConsoleOutputCharacterW/A use it. In server-side, CsrReadConsoleOutputChar and CsrReadConsoleOutputAttrib are merged into SrvReadConsoleOutputString. (Remark: the SrvReadConsoleOutputString name comes from http://j00ru.vexillium.org/csrss_list/api_list.html and I checked that it was indeed the server function that was called by both ReadConsoleOutputAttribute and ReadConsoleOutputCharacter). The idea behind merging these two functions is, that an attribute or a character are instances of the same entity, namely a "code" (what would be called an (ANSI) escape sequence). Therefore I encode them inside the same CSRSS_READ_CONSOLE_OUTPUT_CODE structure and I use it with the previous functions. [CONSRV] - Make use of the CONSOLE_PROCESS_DATA structure (introduced in r57685). - Use CsrValidateMessageBuffer instead of Win32CsrValidateBuffer. - Reorganize conmsg.h a little bit. svn path=/branches/ros-csrss/; revision=57721
This commit is contained in:
parent
7e801b0929
commit
2006c3bf86
4 changed files with 602 additions and 573 deletions
|
@ -211,16 +211,16 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
|||
if (NotChar)
|
||||
LastVirtualKey = msg->wParam;
|
||||
|
||||
DPRINT ("csrss: %s %s %s %s %02x %02x '%lc' %04x\n",
|
||||
Down ? "down" : "up ",
|
||||
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
||||
"char" : "key ",
|
||||
Fake ? "fake" : "real",
|
||||
NotChar ? "notc" : "char",
|
||||
VirtualScanCode,
|
||||
VirtualKeyCode,
|
||||
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
|
||||
ShiftState);
|
||||
DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
|
||||
Down ? "down" : "up ",
|
||||
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
||||
"char" : "key ",
|
||||
Fake ? "fake" : "real",
|
||||
NotChar ? "notc" : "char",
|
||||
VirtualScanCode,
|
||||
VirtualKeyCode,
|
||||
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
|
||||
ShiftState);
|
||||
|
||||
if (Fake)
|
||||
return;
|
||||
|
@ -232,13 +232,15 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
|||
(er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
|
||||
(er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
|
||||
{
|
||||
PCSR_PROCESS current;
|
||||
PCONSOLE_PROCESS_DATA current;
|
||||
PLIST_ENTRY current_entry;
|
||||
|
||||
DPRINT1("Console_Api Ctrl-C\n");
|
||||
|
||||
current_entry = Console->ProcessList.Flink;
|
||||
while (current_entry != &Console->ProcessList)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
|
||||
current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
|
||||
current_entry = current_entry->Flink;
|
||||
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
|
||||
}
|
||||
|
@ -293,69 +295,163 @@ ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
|||
CSR_API(SrvGetConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_PEEK_CONSOLE_INPUT PeekConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.PeekConsoleInputRequest;
|
||||
PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
|
||||
PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCSRSS_CONSOLE Console;
|
||||
PLIST_ENTRY CurrentInput;
|
||||
ConsoleInput* Input;
|
||||
|
||||
DWORD Length;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
PINPUT_RECORD InputRecord;
|
||||
ConsoleInput* Item;
|
||||
UINT NumItems;
|
||||
|
||||
DPRINT("SrvGetConsoleInput\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData, PeekConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
|
||||
if(! NT_SUCCESS(Status))
|
||||
Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ);
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&GetConsoleInputRequest->InputRecord,
|
||||
GetConsoleInputRequest->Length,
|
||||
sizeof(INPUT_RECORD)))
|
||||
{
|
||||
return Status;
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
InputRecord = PeekConsoleInputRequest->InputRecord;
|
||||
Length = PeekConsoleInputRequest->Length;
|
||||
InputRecord = GetConsoleInputRequest->InputRecord;
|
||||
Length = GetConsoleInputRequest->Length;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
/*
|
||||
if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
*/
|
||||
|
||||
NumItems = 0;
|
||||
|
||||
if (! IsListEmpty(&Console->InputEvents))
|
||||
if (GetConsoleInputRequest->bRead) // Read input.
|
||||
{
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
GetConsoleInputRequest->Event = ProcessData->ConsoleEvent;
|
||||
|
||||
while (CurrentItem != &Console->InputEvents && NumItems < Length)
|
||||
while (Length > 0)
|
||||
{
|
||||
Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
|
||||
BOOLEAN Done = FALSE;
|
||||
|
||||
++NumItems;
|
||||
*InputRecord = Item->InputEvent;
|
||||
// GetConsoleInputRequest->Event = ProcessData->ConsoleEvent;
|
||||
|
||||
if (PeekConsoleInputRequest->Unicode == FALSE)
|
||||
/* only get input if there is any */
|
||||
CurrentInput = Console->InputEvents.Flink;
|
||||
while (CurrentInput != &Console->InputEvents)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, InputRecord);
|
||||
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
|
||||
if (Done)
|
||||
{
|
||||
GetConsoleInputRequest->MoreEvents = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
|
||||
if (!Done)
|
||||
{
|
||||
GetConsoleInputRequest->InputsRead++;
|
||||
*InputRecord = Input->InputEvent;
|
||||
/* HACK */ Length--;
|
||||
|
||||
// GetConsoleInputRequest->Input = Input->InputEvent;
|
||||
if (GetConsoleInputRequest->Unicode == FALSE)
|
||||
{
|
||||
// ConioInputEventToAnsi(Console, &GetConsoleInputRequest->Input);
|
||||
ConioInputEventToAnsi(Console, InputRecord);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
Done = TRUE;
|
||||
}
|
||||
|
||||
HeapFree(ConSrvHeap, 0, Input);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
if (Done)
|
||||
Status = STATUS_SUCCESS;
|
||||
else
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
if (GetConsoleInputRequest->InputsRead == 0)
|
||||
{
|
||||
Status = NtWaitForSingleObject(GetConsoleInputRequest->Event, FALSE, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// BaseSetLastNTError(Status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing more to read (waiting for more input??), let's just bail */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // Status != STATUS_PENDING ; == STATUS_SUCCESS
|
||||
{
|
||||
if (!GetConsoleInputRequest->MoreEvents)
|
||||
{
|
||||
/* nothing more to read, bail */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Peek input.
|
||||
{
|
||||
UINT NumInputs = 0;
|
||||
|
||||
if (!IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
CurrentInput = Console->InputEvents.Flink;
|
||||
|
||||
while (CurrentInput != &Console->InputEvents && NumInputs < Length)
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
||||
|
||||
++NumInputs;
|
||||
*InputRecord = Input->InputEvent;
|
||||
|
||||
if (GetConsoleInputRequest->Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, InputRecord);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
GetConsoleInputRequest->Length = NumInputs;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
PeekConsoleInputRequest->Length = NumItems;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(SrvWriteConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_WRITE_CONSOLE_INPUT WriteConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleInputRequest;
|
||||
PINPUT_RECORD InputRecord;
|
||||
PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
DWORD Length;
|
||||
DWORD i;
|
||||
|
||||
|
@ -370,7 +466,7 @@ CSR_API(SrvWriteConsoleInput)
|
|||
InputRecord = WriteConsoleInputRequest->InputRecord;
|
||||
Length = WriteConsoleInputRequest->Length;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
|
@ -398,6 +494,7 @@ CSR_API(SrvWriteConsoleInput)
|
|||
|
||||
CSR_API(SrvReadConsole)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
|
@ -405,9 +502,8 @@ CSR_API(SrvReadConsole)
|
|||
PWCHAR UnicodeBuffer;
|
||||
ULONG i = 0;
|
||||
ULONG nNumberOfCharsToRead, CharSize;
|
||||
PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("SrvReadConsole\n");
|
||||
|
||||
|
@ -415,22 +511,55 @@ CSR_API(SrvReadConsole)
|
|||
|
||||
nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
|
||||
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ReadConsoleRequest->Buffer,
|
||||
ReadConsoleRequest->BufferSize,
|
||||
sizeof(BYTE)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Buffer = (PCHAR)ReadConsoleRequest->Buffer;
|
||||
UnicodeBuffer = (PWCHAR)Buffer;
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Buffer, nNumberOfCharsToRead, CharSize))
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
/*
|
||||
if (!Win32CsrValidateBuffer(ProcessData->Process, Buffer, nNumberOfCharsToRead, CharSize))
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
*/
|
||||
|
||||
Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle,
|
||||
&Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent;
|
||||
|
||||
/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/
|
||||
do
|
||||
{
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
Status = NtWaitForSingleObject(ReadConsoleRequest->EventHandle,
|
||||
FALSE,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Wait for console input failed!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/******/
|
||||
|
||||
if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
|
||||
{
|
||||
// return STATUS_INVALID_PARAMETER;
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
// goto done;
|
||||
}
|
||||
|
||||
// ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent;
|
||||
|
||||
Status = STATUS_PENDING; /* we haven't read anything (yet) */
|
||||
if (Console->Mode & ENABLE_LINE_INPUT)
|
||||
{
|
||||
|
@ -531,68 +660,11 @@ CSR_API(SrvReadConsole)
|
|||
}
|
||||
done:
|
||||
ReadConsoleRequest->NrCharactersRead = i;
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
/******/
|
||||
}
|
||||
|
||||
CSR_API(CsrReadInputEvent)
|
||||
{
|
||||
PCSRSS_READ_INPUT ReadInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadInputRequest;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Done = FALSE;
|
||||
ConsoleInput *Input;
|
||||
|
||||
DPRINT("CsrReadInputEvent\n");
|
||||
|
||||
ReadInputRequest->Event = ProcessData->ConsoleEvent;
|
||||
|
||||
Status = ConioLockConsole(ProcessData, ReadInputRequest->ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* only get input if there is any */
|
||||
CurrentEntry = Console->InputEvents.Flink;
|
||||
while (CurrentEntry != &Console->InputEvents)
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
|
||||
if (Done)
|
||||
{
|
||||
ReadInputRequest->MoreEvents = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
|
||||
if (!Done)
|
||||
{
|
||||
ReadInputRequest->Input = Input->InputEvent;
|
||||
if (ReadInputRequest->Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, &ReadInputRequest->Input);
|
||||
}
|
||||
Done = TRUE;
|
||||
}
|
||||
|
||||
HeapFree(ConSrvHeap, 0, Input);
|
||||
}
|
||||
|
||||
if (Done)
|
||||
Status = STATUS_SUCCESS;
|
||||
else
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
while (Status == STATUS_PENDING);
|
||||
/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
|
@ -601,22 +673,19 @@ CSR_API(CsrReadInputEvent)
|
|||
|
||||
CSR_API(SrvFlushConsoleInputBuffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_FLUSH_INPUT_BUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSRSS_CONSOLE Console;
|
||||
ConsoleInput* Input;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("SrvFlushConsoleInputBuffer\n");
|
||||
|
||||
Status = ConioLockConsole(CsrGetClientThread()->Process,
|
||||
Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
|
||||
FlushInputBufferRequest->ConsoleInput,
|
||||
&Console,
|
||||
GENERIC_WRITE);
|
||||
if(! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Discard all entries in the input event queue */
|
||||
while (!IsListEmpty(&Console->InputEvents))
|
||||
|
@ -638,24 +707,21 @@ CSR_API(SrvGetConsoleNumberOfInputEvents)
|
|||
NTSTATUS Status;
|
||||
PCSRSS_GET_NUM_INPUT_EVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
PLIST_ENTRY CurrentInput;
|
||||
DWORD NumEvents;
|
||||
|
||||
DPRINT("SrvGetConsoleNumberOfInputEvents\n");
|
||||
|
||||
Status = ConioLockConsole(CsrGetClientThread()->Process, GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Status = ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), GetNumInputEventsRequest->ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
CurrentInput = Console->InputEvents.Flink;
|
||||
NumEvents = 0;
|
||||
|
||||
/* If there are any events ... */
|
||||
while (CurrentItem != &Console->InputEvents)
|
||||
while (CurrentInput != &Console->InputEvents)
|
||||
{
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
NumEvents++;
|
||||
}
|
||||
|
||||
|
|
|
@ -436,7 +436,7 @@ ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale)
|
|||
CSR_API(SrvReadConsoleOutput)
|
||||
{
|
||||
PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputRequest;
|
||||
PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCHAR_INFO CharInfo;
|
||||
PCHAR_INFO CurCharInfo;
|
||||
PCSRSS_SCREEN_BUFFER Buff;
|
||||
|
@ -453,26 +453,32 @@ CSR_API(SrvReadConsoleOutput)
|
|||
|
||||
DPRINT("SrvReadConsoleOutput\n");
|
||||
|
||||
Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
CharInfo = ReadConsoleOutputRequest->CharInfo;
|
||||
ReadRegion = ReadConsoleOutputRequest->ReadRegion;
|
||||
BufferSize = ReadConsoleOutputRequest->BufferSize;
|
||||
BufferCoord = ReadConsoleOutputRequest->BufferCoord;
|
||||
|
||||
/* FIXME: Is this correct? */
|
||||
CodePage = ProcessData->Console->OutputCodePage;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, CharInfo,
|
||||
if (!CsrValidateMessageBuffer(ApiMessage,
|
||||
(PVOID*)&ReadConsoleOutputRequest->CharInfo,
|
||||
BufferSize.X * BufferSize.Y,
|
||||
sizeof(CHAR_INFO)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
/*
|
||||
if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
|
||||
BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
|
||||
{
|
||||
ConioUnlockScreenBuffer(Buff);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
*/
|
||||
|
||||
Status = ConioLockScreenBuffer(ProcessData, ReadConsoleOutputRequest->ConsoleHandle, &Buff, GENERIC_READ);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* FIXME: Is this correct? */
|
||||
CodePage = ProcessData->Console->OutputCodePage;
|
||||
|
||||
SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
|
||||
SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
|
||||
|
@ -480,7 +486,7 @@ CSR_API(SrvReadConsoleOutput)
|
|||
ReadRegion.Right = ReadRegion.Left + SizeX;
|
||||
|
||||
ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
|
||||
if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
|
||||
if (!ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
|
||||
{
|
||||
ConioUnlockScreenBuffer(Buff);
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -495,6 +501,7 @@ CSR_API(SrvReadConsoleOutput)
|
|||
{
|
||||
if (ReadConsoleOutputRequest->Unicode)
|
||||
{
|
||||
// ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
|
||||
MultiByteToWideChar(CodePage, 0,
|
||||
(PCHAR)Ptr++, 1,
|
||||
&CurCharInfo->Char.UnicodeChar, 1);
|
||||
|
@ -691,45 +698,82 @@ CSR_API(SrvWriteConsoleOutput)
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrReadConsoleOutputChar)
|
||||
CSR_API(SrvReadConsoleOutputString)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCharRequest;
|
||||
PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputCodeRequest;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSRSS_SCREEN_BUFFER Buff;
|
||||
USHORT CodeType;
|
||||
DWORD Xpos, Ypos;
|
||||
PCHAR ReadBuffer;
|
||||
PVOID ReadBuffer;
|
||||
DWORD i;
|
||||
ULONG CharSize;
|
||||
CHAR Char;
|
||||
ULONG CodeSize;
|
||||
BYTE Code;
|
||||
|
||||
DPRINT("CsrReadConsoleOutputChar\n");
|
||||
DPRINT("SrvReadConsoleOutputString\n");
|
||||
|
||||
ReadBuffer = ReadConsoleOutputCharRequest->String;
|
||||
ReadBuffer = ReadConsoleOutputCodeRequest->pCode.pCode;
|
||||
|
||||
CharSize = (ReadConsoleOutputCharRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
|
||||
|
||||
Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputCharRequest->ConsoleHandle, &Buff, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
CodeType = ReadConsoleOutputCodeRequest->CodeType;
|
||||
switch (CodeType)
|
||||
{
|
||||
return Status;
|
||||
case CODE_ASCII:
|
||||
CodeSize = sizeof(CHAR);
|
||||
break;
|
||||
|
||||
case CODE_UNICODE:
|
||||
CodeSize = sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
CodeSize = sizeof(WORD);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadConsoleOutputCodeRequest->ConsoleHandle, &Buff, GENERIC_READ);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
|
||||
Xpos = ReadConsoleOutputCharRequest->ReadCoord.X;
|
||||
Ypos = (ReadConsoleOutputCharRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
|
||||
Xpos = ReadConsoleOutputCodeRequest->ReadCoord.X;
|
||||
Ypos = (ReadConsoleOutputCodeRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
|
||||
|
||||
for (i = 0; i < ReadConsoleOutputCharRequest->NumCharsToRead; ++i)
|
||||
/*
|
||||
* MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
|
||||
*
|
||||
* If the number of attributes (resp. characters) to be read from extends
|
||||
* beyond the end of the specified screen buffer row, attributes (resp.
|
||||
* characters) are read from the next row. If the number of attributes
|
||||
* (resp. characters) to be read from extends beyond the end of the console
|
||||
* screen buffer, attributes (resp. characters) up to the end of the console
|
||||
* screen buffer are read.
|
||||
*
|
||||
* TODO: Do NOT loop up to NumCodesToRead, but stop before
|
||||
* if we are going to overflow...
|
||||
*/
|
||||
for (i = 0; i < ReadConsoleOutputCodeRequest->NumCodesToRead; ++i)
|
||||
{
|
||||
Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
|
||||
Code = Buff->Buffer[2 * (Xpos + Ypos * Buff->MaxX) + (CodeType == CODE_ATTRIBUTE ? 1 : 0)];
|
||||
|
||||
if(ReadConsoleOutputCharRequest->Unicode)
|
||||
switch (CodeType)
|
||||
{
|
||||
ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char);
|
||||
ReadBuffer += sizeof(WCHAR);
|
||||
case CODE_UNICODE:
|
||||
ConsoleAnsiCharToUnicodeChar(Console, (PWCHAR)ReadBuffer, (PCHAR)&Code);
|
||||
break;
|
||||
|
||||
case CODE_ASCII:
|
||||
*(PCHAR)ReadBuffer = (CHAR)Code;
|
||||
break;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
*(PWORD)ReadBuffer = (WORD)Code;
|
||||
break;
|
||||
}
|
||||
else
|
||||
*(ReadBuffer++) = Char;
|
||||
ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
|
||||
|
||||
Xpos++;
|
||||
|
||||
|
@ -745,78 +789,28 @@ CSR_API(CsrReadConsoleOutputChar)
|
|||
}
|
||||
}
|
||||
|
||||
*ReadBuffer = 0;
|
||||
ReadConsoleOutputCharRequest->EndCoord.X = Xpos;
|
||||
ReadConsoleOutputCharRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
|
||||
switch (CodeType)
|
||||
{
|
||||
case CODE_UNICODE:
|
||||
*(PWCHAR)ReadBuffer = 0;
|
||||
break;
|
||||
|
||||
case CODE_ASCII:
|
||||
*(PCHAR)ReadBuffer = 0;
|
||||
break;
|
||||
|
||||
case CODE_ATTRIBUTE:
|
||||
*(PWORD)ReadBuffer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ReadConsoleOutputCodeRequest->EndCoord.X = Xpos;
|
||||
ReadConsoleOutputCodeRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
|
||||
|
||||
ConioUnlockScreenBuffer(Buff);
|
||||
|
||||
ReadConsoleOutputCharRequest->CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCharRequest->String) / CharSize;
|
||||
if (ReadConsoleOutputCharRequest->CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE))
|
||||
{
|
||||
DPRINT1("Length won't fit in message\n");
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrReadConsoleOutputAttrib)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleOutputAttribRequest;
|
||||
PCSRSS_SCREEN_BUFFER Buff;
|
||||
DWORD Xpos, Ypos;
|
||||
PWORD ReadBuffer;
|
||||
DWORD i;
|
||||
DWORD CurrentLength;
|
||||
|
||||
DPRINT("CsrReadConsoleOutputAttrib\n");
|
||||
|
||||
ReadBuffer = ReadConsoleOutputAttribRequest->Attribute;
|
||||
|
||||
Status = ConioLockScreenBuffer(CsrGetClientThread()->Process, ReadConsoleOutputAttribRequest->ConsoleHandle, &Buff, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Xpos = ReadConsoleOutputAttribRequest->ReadCoord.X;
|
||||
Ypos = (ReadConsoleOutputAttribRequest->ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
|
||||
|
||||
for (i = 0; i < ReadConsoleOutputAttribRequest->NumAttrsToRead; ++i)
|
||||
{
|
||||
*ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1];
|
||||
|
||||
ReadBuffer++;
|
||||
Xpos++;
|
||||
|
||||
if (Xpos == Buff->MaxX)
|
||||
{
|
||||
Xpos = 0;
|
||||
Ypos++;
|
||||
|
||||
if (Ypos == Buff->MaxY)
|
||||
{
|
||||
Ypos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ReadBuffer = 0;
|
||||
|
||||
ReadConsoleOutputAttribRequest->EndCoord.X = Xpos;
|
||||
ReadConsoleOutputAttribRequest->EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
|
||||
|
||||
ConioUnlockScreenBuffer(Buff);
|
||||
|
||||
CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB)
|
||||
+ ReadConsoleOutputAttribRequest->NumAttrsToRead * sizeof(WORD);
|
||||
if (CurrentLength > sizeof(CSR_API_MESSAGE))
|
||||
{
|
||||
DPRINT1("Length won't fit in message\n");
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
ReadConsoleOutputCodeRequest->CodesRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)ReadConsoleOutputCodeRequest->pCode.pCode) / CodeSize;
|
||||
// <= ReadConsoleOutputCodeRequest->NumCodesToRead
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue