[CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 24 Jan 2013 20:48:42 +0000 (20:48 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 24 Jan 2013 20:48:42 +0000 (20:48 +0000)
- 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

win32ss/user/consrv/coninput.c
win32ss/user/consrv/conio.h
win32ss/user/consrv/conoutput.c
win32ss/user/consrv/console.c
win32ss/user/consrv/consrv.h
win32ss/user/consrv/handle.c

index a938ec7..8bff04a 100644 (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;
index 3da36f2..e096162 100644 (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);
index 8b1e02f..e3967f9 100644 (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;
index cac5d83..80b0089 100644 (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
     {
index d04872d..2973ff0 100644 (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);
index f2b6aa4..6de812f 100644 (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;
 }