- Start to implement waiting threads notifications. They can be notified by:
  * the required action (screen displaying lock/unlock, presence of new characters in the input buffer),
  * the fact that the application terminates,
  * we close a (input) handle.
  TODO: When we notify them by calling CsrNotifyWait, they are not dereferenced automatically, but they can be
  by calling a dedicated CSR function. We need to know where it is the best to dereference them.
- Correct a bug introduced in revision r58191, which broke console input mode changes (in SrvSetConsoleMode and SrvGetConsoleMode).

svn path=/branches/ros-csrss/; revision=58211
This commit is contained in:
Hermès Bélusca-Maïto
2013-01-24 20:48:42 +00:00
parent 670f805765
commit fe7b0f74d3
6 changed files with 248 additions and 114 deletions
+164 -91
View File
@@ -27,8 +27,9 @@
typedef struct _GET_INPUT_INFO
{
PCONSOLE_PROCESS_DATA ProcessData;
PCONSOLE Console;
PCSR_THREAD CallingThread; // The thread which called the input API.
PCONSOLE_IO_HANDLE HandleEntry; // The handle data associated with the wait thread.
PCONSOLE_INPUT_BUFFER InputBuffer; // The input buffer corresponding to the handle.
} GET_INPUT_INFO, *PGET_INPUT_INFO;
@@ -315,11 +316,11 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
CapturedInputInfo = RtlAllocateHeap(ConSrvHeap, 0, sizeof(GET_INPUT_INFO));
if (!CapturedInputInfo) return STATUS_NO_MEMORY;
memmove(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
RtlMoveMemory(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
if (!CsrCreateWait(&InputInfo->Console->InputBuffer.ReadWaitQueue,
if (!CsrCreateWait(&InputInfo->InputBuffer->ReadWaitQueue,
WaitFunction,
CsrGetClientThread(),
InputInfo->CallingThread,
ApiMessage,
CapturedInputInfo,
NULL))
@@ -353,11 +354,43 @@ ReadInputBufferThread(IN PLIST_ENTRY WaitList,
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
PCONSOLE_IO_HANDLE InputHandle = (PCONSOLE_IO_HANDLE)WaitArgument2;
DPRINT1("ReadInputBufferThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
/*
* Somebody is closing a handle to this input buffer,
* by calling Win32CsrCloseHandleEntry.
* See whether we are linked to that handle (ie. we
* are a waiter for this handle), and if so, return.
*/
if (InputHandle == InputInfo->HandleEntry)
{
Status = STATUS_ALERTED;
goto Quit;
}
/*
* If we are notified of the process termination via a call
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
* CsrDestroyThread, just return.
*/
if (WaitFlags & CsrProcessTerminating)
{
Status = STATUS_THREAD_IS_TERMINATING;
goto Quit;
}
/*
* If we go there, that means we are notified for some new input.
* The console is therefore already locked.
*/
Status = ReadInputBuffer(InputInfo,
GetInputRequest->bRead,
WaitApiMessage,
FALSE);
Quit:
if (Status != STATUS_PENDING)
{
WaitApiMessage->Status = Status;
@@ -373,7 +406,9 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL)
{
if (IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents))
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
if (IsListEmpty(&InputBuffer->InputEvents))
{
if (Wait)
{
@@ -397,9 +432,9 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
PINPUT_RECORD InputRecord = GetInputRequest->InputRecord;
/* Only get input if there is any */
CurrentInput = InputInfo->Console->InputBuffer.InputEvents.Flink;
CurrentInput = InputBuffer->InputEvents.Flink;
while ( CurrentInput != &InputInfo->Console->InputBuffer.InputEvents &&
while ( CurrentInput != &InputBuffer->InputEvents &&
GetInputRequest->InputsRead < Length )
{
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
@@ -409,7 +444,7 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
if (GetInputRequest->Unicode == FALSE)
{
ConioInputEventToAnsi(InputInfo->Console, InputRecord);
ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
}
InputRecord++;
@@ -422,9 +457,9 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
}
}
if (IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents))
if (IsListEmpty(&InputBuffer->InputEvents))
{
ResetEvent(InputInfo->Console->InputBuffer.ActiveEvent);
ResetEvent(InputBuffer->ActiveEvent);
}
/* We read all the inputs available, we return success */
@@ -450,10 +485,42 @@ ReadCharsThread(IN PLIST_ENTRY WaitList,
NTSTATUS Status;
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
PCONSOLE_IO_HANDLE InputHandle = (PCONSOLE_IO_HANDLE)WaitArgument2;
DPRINT1("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
/*
* Somebody is closing a handle to this input buffer,
* by calling Win32CsrCloseHandleEntry.
* See whether we are linked to that handle (ie. we
* are a waiter for this handle), and if so, return.
*/
if (InputHandle == InputInfo->HandleEntry)
{
Status = STATUS_ALERTED;
goto Quit;
}
/*
* If we are notified of the process termination via a call
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
* CsrDestroyThread, just return.
*/
if (WaitFlags & CsrProcessTerminating)
{
Status = STATUS_THREAD_IS_TERMINATING;
goto Quit;
}
/*
* If we go there, that means we are notified for some new input.
* The console is therefore already locked.
*/
Status = ReadChars(InputInfo,
WaitApiMessage,
FALSE);
Quit:
if (Status != STATUS_PENDING)
{
WaitApiMessage->Status = Status;
@@ -471,6 +538,8 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
BOOL WaitForMoreToRead = TRUE; // TRUE : Wait if more to read ; FALSE : Don't wait.
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
PCONSOLE Console = InputBuffer->Header.Console;
PLIST_ENTRY CurrentEntry;
ConsoleInput *Input;
PCHAR Buffer = (PCHAR)ReadConsoleRequest->Buffer;
@@ -479,45 +548,45 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
/* We haven't read anything (yet) */
if (InputInfo->Console->InputBuffer.Mode & ENABLE_LINE_INPUT)
if (InputBuffer->Mode & ENABLE_LINE_INPUT)
{
if (InputInfo->Console->LineBuffer == NULL)
if (Console->LineBuffer == NULL)
{
/* Starting a new line */
InputInfo->Console->LineMaxSize = max(256, nNumberOfCharsToRead);
InputInfo->Console->LineBuffer = RtlAllocateHeap(ConSrvHeap, 0, InputInfo->Console->LineMaxSize * sizeof(WCHAR));
if (InputInfo->Console->LineBuffer == NULL)
Console->LineMaxSize = max(256, nNumberOfCharsToRead);
Console->LineBuffer = RtlAllocateHeap(ConSrvHeap, 0, Console->LineMaxSize * sizeof(WCHAR));
if (Console->LineBuffer == NULL)
{
return STATUS_NO_MEMORY;
}
InputInfo->Console->LineComplete = FALSE;
InputInfo->Console->LineUpPressed = FALSE;
InputInfo->Console->LineInsertToggle = 0;
InputInfo->Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
InputInfo->Console->LineSize = ReadConsoleRequest->NrCharactersRead;
InputInfo->Console->LinePos = InputInfo->Console->LineSize;
Console->LineComplete = FALSE;
Console->LineUpPressed = FALSE;
Console->LineInsertToggle = 0;
Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
Console->LineSize = ReadConsoleRequest->NrCharactersRead;
Console->LinePos = Console->LineSize;
/*
* Pre-filling the buffer is only allowed in the Unicode API,
* so we don't need to worry about ANSI <-> Unicode conversion.
*/
memcpy(InputInfo->Console->LineBuffer, Buffer, InputInfo->Console->LineSize * sizeof(WCHAR));
if (InputInfo->Console->LineSize == InputInfo->Console->LineMaxSize)
memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
if (Console->LineSize == Console->LineMaxSize)
{
InputInfo->Console->LineComplete = TRUE;
InputInfo->Console->LinePos = 0;
Console->LineComplete = TRUE;
Console->LinePos = 0;
}
}
/* If we don't have a complete line yet, process the pending input */
while ( !InputInfo->Console->LineComplete &&
!IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents) )
while ( !Console->LineComplete &&
!IsListEmpty(&InputBuffer->InputEvents) )
{
/* Remove input event from queue */
CurrentEntry = RemoveHeadList(&InputInfo->Console->InputBuffer.InputEvents);
if (IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents))
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
if (IsListEmpty(&InputBuffer->InputEvents))
{
ResetEvent(InputInfo->Console->InputBuffer.ActiveEvent);
ResetEvent(InputBuffer->ActiveEvent);
}
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
@@ -525,19 +594,19 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
if (KEY_EVENT == Input->InputEvent.EventType
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
{
LineInputKeyDown(InputInfo->Console, &Input->InputEvent.Event.KeyEvent);
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
}
RtlFreeHeap(ConSrvHeap, 0, Input);
}
/* Check if we have a complete line to read from */
if (InputInfo->Console->LineComplete)
if (Console->LineComplete)
{
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
InputInfo->Console->LinePos != InputInfo->Console->LineSize )
Console->LinePos != Console->LineSize )
{
WCHAR Char = InputInfo->Console->LineBuffer[InputInfo->Console->LinePos++];
WCHAR Char = Console->LineBuffer[Console->LinePos++];
if (ReadConsoleRequest->Unicode)
{
@@ -545,7 +614,7 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
}
else
{
ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
ConsoleInputUnicodeCharToAnsiChar(Console,
&Buffer[ReadConsoleRequest->NrCharactersRead],
&Char);
}
@@ -553,11 +622,11 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
ReadConsoleRequest->NrCharactersRead++;
}
if (InputInfo->Console->LinePos == InputInfo->Console->LineSize)
if (Console->LinePos == Console->LineSize)
{
/* Entire line has been read */
RtlFreeHeap(ConSrvHeap, 0, InputInfo->Console->LineBuffer);
InputInfo->Console->LineBuffer = NULL;
RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
Console->LineBuffer = NULL;
}
WaitForMoreToRead = FALSE;
@@ -567,13 +636,13 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
{
/* Character input */
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
!IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents) )
!IsListEmpty(&InputBuffer->InputEvents) )
{
/* Remove input event from queue */
CurrentEntry = RemoveHeadList(&InputInfo->Console->InputBuffer.InputEvents);
if (IsListEmpty(&InputInfo->Console->InputBuffer.InputEvents))
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
if (IsListEmpty(&InputBuffer->InputEvents))
{
ResetEvent(InputInfo->Console->InputBuffer.ActiveEvent);
ResetEvent(InputBuffer->ActiveEvent);
}
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
@@ -590,7 +659,7 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
}
else
{
ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console,
ConsoleInputUnicodeCharToAnsiChar(Console,
&Buffer[ReadConsoleRequest->NrCharactersRead],
&Char);
}
@@ -621,11 +690,58 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
/* PUBLIC APIS ****************************************************************/
CSR_API(SrvReadConsole)
{
NTSTATUS Status;
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCONSOLE_IO_HANDLE HandleEntry;
PCONSOLE_INPUT_BUFFER InputBuffer;
GET_INPUT_INFO InputInfo;
DPRINT("SrvReadConsole\n");
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ReadConsoleRequest->Buffer,
ReadConsoleRequest->BufferSize,
sizeof(BYTE)))
{
return STATUS_INVALID_PARAMETER;
}
// if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
{
return STATUS_INVALID_PARAMETER;
}
Status = ConioGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
ReadConsoleRequest->NrCharactersRead = 0;
InputInfo.CallingThread = CsrGetClientThread();
InputInfo.HandleEntry = HandleEntry;
InputInfo.InputBuffer = InputBuffer;
Status = ReadChars(&InputInfo,
ApiMessage,
TRUE);
ConioReleaseInputBuffer(InputBuffer, TRUE);
if (Status == STATUS_PENDING)
*ReplyCode = CsrReplyPending;
return Status;
}
CSR_API(SrvGetConsoleInput)
{
NTSTATUS Status;
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCONSOLE_IO_HANDLE HandleEntry;
PCONSOLE_INPUT_BUFFER InputBuffer;
GET_INPUT_INFO InputInfo;
@@ -641,11 +757,12 @@ CSR_API(SrvGetConsoleInput)
GetInputRequest->InputsRead = 0;
Status = ConioGetInputBuffer(ProcessData, GetInputRequest->InputHandle, &InputBuffer, GENERIC_READ, TRUE);
Status = ConioGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
if(!NT_SUCCESS(Status)) return Status;
InputInfo.ProcessData = ProcessData;
InputInfo.Console = InputBuffer->Header.Console;
InputInfo.CallingThread = CsrGetClientThread();
InputInfo.HandleEntry = HandleEntry;
InputInfo.InputBuffer = InputBuffer;
Status = ReadInputBuffer(&InputInfo,
GetInputRequest->bRead,
@@ -709,50 +826,6 @@ CSR_API(SrvWriteConsoleInput)
return Status;
}
CSR_API(SrvReadConsole)
{
NTSTATUS Status;
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCONSOLE_INPUT_BUFFER InputBuffer;
GET_INPUT_INFO InputInfo;
DPRINT("SrvReadConsole\n");
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ReadConsoleRequest->Buffer,
ReadConsoleRequest->BufferSize,
sizeof(BYTE)))
{
return STATUS_INVALID_PARAMETER;
}
// if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
{
return STATUS_INVALID_PARAMETER;
}
Status = ConioGetInputBuffer(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, GENERIC_READ, TRUE);
if (!NT_SUCCESS(Status)) return Status;
ReadConsoleRequest->NrCharactersRead = 0;
InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
InputInfo.Console = InputBuffer->Header.Console;
Status = ReadChars(&InputInfo,
ApiMessage,
TRUE);
ConioReleaseInputBuffer(InputBuffer, TRUE);
if (Status == STATUS_PENDING)
*ReplyCode = CsrReplyPending;
return Status;
}
CSR_API(SrvFlushConsoleInputBuffer)
{
NTSTATUS Status;
+11 -3
View File
@@ -184,8 +184,12 @@ VOID FASTCALL ConioConsoleCtrlEventTimeout(DWORD Event,
DWORD Timeout);
/* coninput.c */
#define ConioGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), (Access), (LockConsole), CONIO_INPUT_BUFFER_MAGIC)
#define ConioGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), NULL, \
(Access), (LockConsole), CONIO_INPUT_BUFFER_MAGIC)
#define ConioGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), (Entry), \
(Access), (LockConsole), CONIO_INPUT_BUFFER_MAGIC)
#define ConioReleaseInputBuffer(Buff, IsConsoleLocked) \
Win32CsrUnlockObject(&(Buff)->Header, (IsConsoleLocked))
void WINAPI ConioProcessKey(MSG *msg, PCONSOLE Console, BOOL TextMode);
@@ -196,7 +200,11 @@ void WINAPI ConioProcessKey(MSG *msg, PCONSOLE Console, BOOL TextMode);
#define ConioRectWidth(Rect) \
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
#define ConioGetScreenBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), (Access), (LockConsole), CONIO_SCREEN_BUFFER_MAGIC)
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), NULL, \
(Access), (LockConsole), CONIO_SCREEN_BUFFER_MAGIC)
#define ConioGetScreenBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), (Entry), \
(Access), (LockConsole), CONIO_SCREEN_BUFFER_MAGIC)
#define ConioReleaseScreenBuffer(Buff, IsConsoleLocked) \
Win32CsrUnlockObject(&(Buff)->Header, (IsConsoleLocked))
PBYTE FASTCALL ConioCoordToPointer(PCONSOLE_SCREEN_BUFFER Buf, ULONG X, ULONG Y);
+14
View File
@@ -447,10 +447,24 @@ WriteConsoleThread(IN PLIST_ENTRY WaitList,
{
NTSTATUS Status;
DPRINT1("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
/*
* If we are notified of the process termination via a call
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
* CsrDestroyThread, just return.
*/
if (WaitFlags & CsrProcessTerminating)
{
Status = STATUS_THREAD_IS_TERMINATING;
goto Quit;
}
Status = DoWriteConsole(WaitApiMessage,
WaitThread,
FALSE);
Quit:
if (Status != STATUS_PENDING)
{
WaitApiMessage->Status = Status;
+10 -10
View File
@@ -581,20 +581,20 @@ CSR_API(SrvSetConsoleMode)
Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ConsoleModeRequest->ConsoleHandle,
&Object, GENERIC_WRITE, TRUE, 0);
&Object, NULL, GENERIC_WRITE, TRUE, 0);
if (!NT_SUCCESS(Status)) return Status;
Status = STATUS_SUCCESS;
if (CONIO_INPUT_BUFFER_MAGIC == Object->Type)
{
PCONSOLE Console = (PCONSOLE)Object;
Console->InputBuffer.Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_INPUT_MODE_VALID;
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
InputBuffer->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_INPUT_MODE_VALID;
}
else if (CONIO_SCREEN_BUFFER_MAGIC == Object->Type)
{
PCONSOLE_SCREEN_BUFFER Buff = (PCONSOLE_SCREEN_BUFFER)Object;
Buff->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_OUTPUT_MODE_VALID;
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
Buffer->Mode = ConsoleModeRequest->ConsoleMode & CONSOLE_OUTPUT_MODE_VALID;
}
else
{
@@ -616,20 +616,20 @@ CSR_API(SrvGetConsoleMode)
Status = Win32CsrLockObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
ConsoleModeRequest->ConsoleHandle,
&Object, GENERIC_READ, TRUE, 0);
&Object, NULL, GENERIC_READ, TRUE, 0);
if (!NT_SUCCESS(Status)) return Status;
Status = STATUS_SUCCESS;
if (CONIO_INPUT_BUFFER_MAGIC == Object->Type)
{
PCONSOLE Console = (PCONSOLE)Object;
ConsoleModeRequest->ConsoleMode = Console->InputBuffer.Mode;
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
ConsoleModeRequest->ConsoleMode = InputBuffer->Mode;
}
else if (CONIO_SCREEN_BUFFER_MAGIC == Object->Type)
{
PCONSOLE_SCREEN_BUFFER Buff = (PCONSOLE_SCREEN_BUFFER)Object;
ConsoleModeRequest->ConsoleMode = Buff->Mode;
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
ConsoleModeRequest->ConsoleMode = Buffer->Mode;
}
else
{
+2 -1
View File
@@ -155,7 +155,8 @@ NTSTATUS FASTCALL Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
DWORD ShareMode);
NTSTATUS FASTCALL Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle,
Object_t **Object,
Object_t** Object,
PCONSOLE_IO_HANDLE* Entry OPTIONAL,
DWORD Access,
BOOL LockConsole,
ULONG Type);
+47 -9
View File
@@ -52,7 +52,29 @@ Win32CsrCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
/// LOCK /// PCONSOLE Console = Object->Console;
/// LOCK /// EnterCriticalSection(&Console->Lock);
/// TODO: HERE, trigger input waiting threads.
/*
* If this is a input handle, notify and dereference
* all the waits related to this handle.
*/
if (Object->Type == CONIO_INPUT_BUFFER_MAGIC)
{
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
/*
* Wake up all the writing waiters related to this handle for this
* input buffer, if any, then dereference them and purge them all
* from the list.
* To select them amongst all the waiters for this input buffer,
* pass the handle pointer to the waiters, then they will check
* whether or not they are related to this handle and if so, they
* return.
*/
CsrNotifyWait(&InputBuffer->ReadWaitQueue,
WaitAll,
NULL,
(PVOID)Entry);
// TODO: Dereference the notified waits.
}
/* If the last handle to a screen buffer is closed, delete it... */
if (AdjustHandleCounts(Entry, -1) == 0)
@@ -318,33 +340,49 @@ NTSTATUS
FASTCALL
Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle,
Object_t **Object,
Object_t** Object,
PCONSOLE_IO_HANDLE* Entry OPTIONAL,
DWORD Access,
BOOL LockConsole,
ULONG Type)
{
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
PCONSOLE_IO_HANDLE HandleEntry = NULL;
Object_t* ObjectEntry = NULL;
ASSERT(Object);
if (Entry) *Entry = NULL;
// DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
// Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if ( !IsConsoleHandle(Handle) ||
h >= ProcessData->HandleTableSize ||
(*Object = ProcessData->HandleTable[h].Object) == NULL ||
(ProcessData->HandleTable[h].Access & Access) == 0 ||
(Type != 0 && (*Object)->Type != Type) )
if ( IsConsoleHandle(Handle) &&
h < ProcessData->HandleTableSize )
{
HandleEntry = &ProcessData->HandleTable[h];
ObjectEntry = HandleEntry->Object;
}
if ( HandleEntry == NULL ||
ObjectEntry == NULL ||
(HandleEntry->Access & Access) == 0 ||
(Type != 0 && ObjectEntry->Type != Type) )
{
DPRINT1("CsrGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
_InterlockedIncrement(&(*Object)->Console->ReferenceCount);
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
if (LockConsole) EnterCriticalSection(&(*Object)->Console->Lock);
if (LockConsole) EnterCriticalSection(&ObjectEntry->Console->Lock);
/* Return the objects to the caller */
*Object = ObjectEntry;
if (Entry) *Entry = HandleEntry;
return STATUS_SUCCESS;
}