Author: hbelusca Date: Sat Mar 30 18:44:56 2013 New Revision: 58615
URL: http://svn.reactos.org/svn/reactos?rev=58615&view=rev Log: [CONSOLE.DLL] - Fix passing and retrieving gui terminal front-end information. - Fix default (global) console parameters saving.
[CONSRV] - PSEH2-protect calls to CreateRemoteThread when 1. calling console app. control handlers and 2. retrieving console settings from console.dll. - Introduce a new way of locking consoles when being used, and store them in a list.
Added: branches/ros-csrss/win32ss/user/consrv/console.h (with props) Modified: branches/ros-csrss/dll/cpl/console/console.c branches/ros-csrss/win32ss/user/consrv/coninput.c branches/ros-csrss/win32ss/user/consrv/conio.h branches/ros-csrss/win32ss/user/consrv/conoutput.c branches/ros-csrss/win32ss/user/consrv/console.c branches/ros-csrss/win32ss/user/consrv/consrv.h branches/ros-csrss/win32ss/user/consrv/guiconsole.c branches/ros-csrss/win32ss/user/consrv/guisettings.c branches/ros-csrss/win32ss/user/consrv/handle.c branches/ros-csrss/win32ss/user/consrv/init.c
Modified: branches/ros-csrss/dll/cpl/console/console.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/dll/cpl/console/consol... ============================================================================== --- branches/ros-csrss/dll/cpl/console/console.c [iso-8859-1] (original) +++ branches/ros-csrss/dll/cpl/console/console.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -86,6 +86,8 @@ InitConsoleDefaults(PCONSOLE_PROPS pConInfo) { PGUI_CONSOLE_INFO GuiInfo = NULL; + + /* FIXME: Get also the defaults from the registry */
/* Initialize the default properties */ pConInfo->ci.HistoryBufferSize = 50; @@ -108,7 +110,8 @@ /* Adapted for holding GUI terminal information */ pConInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO); GuiInfo = pConInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pConInfo + 1); - GuiInfo->FaceName[0] = L'\0'; + wcsncpy(GuiInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !! + // GuiInfo->FaceName[0] = L'\0'; GuiInfo->FontFamily = FF_DONTCARE; GuiInfo->FontSize = 0; GuiInfo->FontWeight = FW_DONTCARE; @@ -166,16 +169,35 @@ ApplyConsoleInfo(HWND hwndDlg, PCONSOLE_PROPS pConInfo) { - INT_PTR res = 0; - - res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc); - if (res == IDCANCEL) - { - /* Don't destroy when user presses cancel */ - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); - return TRUE; - } - else if (res == IDC_RADIO_APPLY_ALL || res == IDC_RADIO_APPLY_CURRENT) + BOOL SetParams = FALSE; + BOOL SaveParams = FALSE; + + /* + * If we are setting the default parameters, just save them, + * otherwise display the save-confirmation dialog. + */ + if (pConInfo->ShowDefaultParams) + { + SetParams = TRUE; + SaveParams = TRUE; + } + else + { + INT_PTR res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc); + + SetParams = (res != IDCANCEL); + SaveParams = (res == IDC_RADIO_APPLY_ALL); + + if (SetParams == FALSE) + { + /* Don't destroy when user presses cancel */ + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); + // return TRUE; + } + } + + // if (res == IDC_RADIO_APPLY_ALL || res == IDC_RADIO_APPLY_CURRENT) + if (SetParams) { HANDLE hSection; PCONSOLE_PROPS pSharedInfo; @@ -207,10 +229,15 @@ /* We are applying the chosen configuration */ pConInfo->AppliedConfig = TRUE;
- /* Copy the console info into the section */ + /* + * Copy the console information into the section and + * offsetize the address of terminal-specific information. + * Do not perform the offsetization in pConInfo as it is + * likely to be reused later on. Instead, do it in pSharedInfo + * after having copied all the data. + */ RtlCopyMemory(pSharedInfo, pConInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO)); - /* Offsetize */ - pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pSharedInfo->TerminalInfo.TermInfo - (ULONG_PTR)pSharedInfo); + pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo->TerminalInfo.TermInfo - (ULONG_PTR)pConInfo);
/* Unmap it */ UnmapViewOfFile(pSharedInfo); @@ -220,11 +247,10 @@ SendMessage(pConInfo->hConsoleWindow, PM_APPLY_CONSOLE_INFO, (WPARAM)hSection, - (LPARAM)(res == IDC_RADIO_APPLY_ALL)); + (LPARAM)SaveParams);
/* Close the section and return */ CloseHandle(hSection); - return TRUE; }
return TRUE;
Modified: branches/ros-csrss/win32ss/user/consrv/coninput.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/coninput.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/coninput.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -685,7 +685,6 @@ return STATUS_INVALID_PARAMETER; }
- // if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize) if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead) { return STATUS_INVALID_PARAMETER; @@ -808,7 +807,7 @@ PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest; PLIST_ENTRY CurrentEntry; PCONSOLE_INPUT_BUFFER InputBuffer; - ConsoleInput* Input; + ConsoleInput* Event;
DPRINT("SrvFlushConsoleInputBuffer\n");
@@ -823,14 +822,12 @@ while (!IsListEmpty(&InputBuffer->InputEvents)) { CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - /* Destroy the event */ - RtlFreeHeap(ConSrvHeap, 0, Input); + Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + RtlFreeHeap(ConSrvHeap, 0, Event); } ResetEvent(InputBuffer->ActiveEvent);
ConSrvReleaseInputBuffer(InputBuffer, TRUE); - return STATUS_SUCCESS; }
Modified: branches/ros-csrss/win32ss/user/consrv/conio.h URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -147,12 +147,27 @@ PVOID OldData; /* Reserved */ } FRONTEND_IFACE, *PFRONTEND_IFACE;
+#if 0 // Temporarily put in consrv.h +/* + * WARNING: Change the state of the console ONLY when the console is locked ! + */ +typedef enum _CONSOLE_STATE +{ + CONSOLE_INITIALIZING, /* Console is initializing */ + CONSOLE_RUNNING , /* Console running */ + CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */ + CONSOLE_IN_DESTRUCTION /* Console in destruction */ +} CONSOLE_STATE, *PCONSOLE_STATE; +#endif + typedef struct _CONSOLE { - LONG ReferenceCount; /* Is incremented each time a handle to a screen-buffer or the input buffer of this console gets referenced, or the console gets locked */ + 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; - - struct _CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */ + CONSOLE_STATE State; /* State of the console */ + + // struct _CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */ + LIST_ENTRY Entry; /* Entry in the list of consoles */ LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */
FRONTEND_IFACE TermIFace; /* Frontend-specific interface */ @@ -218,11 +233,6 @@ #define PAUSED_FROM_SELECTION 0x4
/* console.c */ -VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console); -VOID WINAPI ConSrvInitConsoleSupport(VOID); -NTSTATUS WINAPI ConSrvInitConsole(OUT PCONSOLE* NewConsole, - IN OUT PCONSOLE_START_INFO ConsoleStartInfo, - IN PCSR_PROCESS ConsoleLeaderProcess); VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags); VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags); ULONG FASTCALL ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
Modified: branches/ros-csrss/win32ss/user/consrv/conoutput.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/conoutput.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/conoutput.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -1278,15 +1278,18 @@
DPRINT("SrvCreateConsoleScreenBuffer\n");
- RtlEnterCriticalSection(&ProcessData->HandleTableLock); + // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
Status = ConSrvGetConsole(ProcessData, &Console, TRUE); if (!NT_SUCCESS(Status)) { - RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); return Status; }
+ RtlEnterCriticalSection(&ProcessData->HandleTableLock); + + /* if (Console->ActiveBuffer) { ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize; @@ -1298,6 +1301,23 @@
IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible; CursorSize = Console->ActiveBuffer->CursorInfo.dwSize; + } + */ + + // This is Windows' behaviour + { + ScreenBufferSize = Console->ConsoleSize; // Use the current console size + if (ScreenBufferSize.X == 0) ScreenBufferSize.X = 1; + if (ScreenBufferSize.Y == 0) ScreenBufferSize.Y = 1; + + if (Console->ActiveBuffer) + { + ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib; + PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib; + + IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible; + CursorSize = Console->ActiveBuffer->CursorInfo.dwSize; + } }
Status = ConSrvCreateScreenBuffer(Console, @@ -1309,6 +1329,7 @@ CursorSize); if (NT_SUCCESS(Status)) { + /* Insert the new handle inside the process handles table */ Status = ConSrvInsertObject(ProcessData, &CreateScreenBufferRequest->OutputHandle, &Buff->Header, @@ -1317,10 +1338,11 @@ CreateScreenBufferRequest->ShareMode); }
+ // ConSrvReleaseConsole(Console, TRUE); + + RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + ConSrvReleaseConsole(Console, TRUE); - - RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - return Status; }
Modified: branches/ros-csrss/win32ss/user/consrv/console.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -21,11 +21,18 @@ #include "tuiconsole.h" #endif
+#include "console.h" + #include <shlwapi.h> #include <shlobj.h>
-//#define NDEBUG +#define NDEBUG #include <debug.h> + +/* GLOBALS ********************************************************************/ + +LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */ +/*static*/ RTL_RESOURCE ListLock;
/* PRIVATE FUNCTIONS **********************************************************/ @@ -44,26 +51,43 @@ DWORD Timeout) { ULONG Status = ERROR_SUCCESS; - HANDLE Thread; - - DPRINT("ConSrvConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess); + + DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
if (ProcessData->CtrlDispatcher) { - Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, - ProcessData->CtrlDispatcher, - UlongToPtr(Event), 0, NULL); - if (NULL == Thread) - { - Status = GetLastError(); - DPRINT1("Failed thread creation (Error: 0x%x)\n", Status); - } - else - { - DPRINT("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); - WaitForSingleObject(Thread, Timeout); - CloseHandle(Thread); - } + _SEH2_TRY + { + HANDLE Thread = NULL; + + _SEH2_TRY + { + Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, + ProcessData->CtrlDispatcher, + UlongToPtr(Event), 0, NULL); + if (NULL == Thread) + { + Status = GetLastError(); + DPRINT1("Failed thread creation (Error: 0x%x)\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 = RtlNtStatusToDosError(_SEH2_GetExceptionCode()); + DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = %08X\n", Status); + } + _SEH2_END; }
return Status; @@ -84,6 +108,10 @@ ULONG Status = ERROR_SUCCESS; PLIST_ENTRY current_entry; PCONSOLE_PROCESS_DATA current; + + /* If the console is already being destroyed, just return */ + if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, FALSE)) + return STATUS_UNSUCCESSFUL;
/* * Loop through the process list, from the most recent process @@ -139,6 +167,18 @@ CsrDereferenceWait(&Console->WriteWaitQueue); } } +} + +VOID WINAPI +ConSrvInitConsoleSupport(VOID) +{ + DPRINT("CONSRV: ConSrvInitConsoleSupport()\n"); + + /* Initialize the console list and its lock */ + InitializeListHead(&ConsoleList); + RtlInitializeResource(&ListLock); + + /* Should call LoadKeyboardLayout */ }
static BOOL @@ -346,6 +386,7 @@ /* * Initialize the console */ + Console->State = CONSOLE_INITIALIZING; InitializeCriticalSection(&Console->Lock); Console->ReferenceCount = 0; InitializeListHead(&Console->ProcessList); @@ -428,6 +469,9 @@ RtlCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle); }
+ /* Lock the console until its initialization is finished */ + // EnterCriticalSection(&Console->Lock); + /* * If we are not in GUI-mode, start the text-mode terminal emulator. * If we fail, try to start the GUI-mode terminal emulator. @@ -480,14 +524,33 @@ RtlFreeUnicodeString(&Console->OriginalTitle); ConioDeleteScreenBuffer(NewBuffer); CloseHandle(Console->InputBuffer.ActiveEvent); + // LeaveCriticalSection(&Console->Lock); DeleteCriticalSection(&Console->Lock); RtlFreeHeap(ConSrvHeap, 0, Console); return Status; } }
+ DPRINT1("Terminal initialized\n"); + + /* All went right, so add the console to the list */ + ConSrvLockConsoleListExclusive(); + DPRINT1("Insert in the list\n"); + InsertTailList(&ConsoleList, &Console->Entry); + + /* The initialization is finished */ + DPRINT1("Change state\n"); + Console->State = CONSOLE_RUNNING; + + /* Unlock the console */ + // LeaveCriticalSection(&Console->Lock); + + /* Unlock the console list */ + ConSrvUnlockConsoleList(); + /* Copy buffer contents to screen */ ConioDrawConsole(Console); + DPRINT1("Console drawn\n");
/* Return the newly created console to the caller and a success code too */ *NewConsole = Console; @@ -495,30 +558,100 @@ }
VOID WINAPI -ConSrvInitConsoleSupport(VOID) -{ - DPRINT("CONSRV: ConSrvInitConsoleSupport()\n"); - - /* Should call LoadKeyboardLayout */ -} - -VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console) { - ConsoleInput *Event; - - DPRINT("ConSrvDeleteConsole\n"); - - /* Drain input event queue */ - while (Console->InputBuffer.InputEvents.Flink != &Console->InputBuffer.InputEvents) - { - Event = (ConsoleInput *) Console->InputBuffer.InputEvents.Flink; - Console->InputBuffer.InputEvents.Flink = Console->InputBuffer.InputEvents.Flink->Flink; - Console->InputBuffer.InputEvents.Flink->Flink->Blink = &Console->InputBuffer.InputEvents; + PLIST_ENTRY CurrentEntry; + ConsoleInput* Event; + + DPRINT1("ConSrvDeleteConsole\n"); + + /* + * Forbid validation of any console by other threads + * during the deletion of this console. + */ + ConSrvLockConsoleListExclusive(); + + /* Check the existence of the console, and if it's ok, continue */ + if (!ConSrvValidatePointer(Console)) + { + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); + return; + } + + /* + * If the console is already being destroyed + * (thus not running), just return. + */ + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) + { + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); + return; + } + + /* + * We are about to be destroyed. Signal it to other people + * so that they can terminate what they are doing, and that + * they cannot longer validate the console. + */ + Console->State = CONSOLE_TERMINATING; + + /* + * Allow other threads to finish their job: basically, unlock + * all other calls to EnterCriticalSection(&Console->Lock); by + * ConSrvValidateConsole(Unsafe) functions so that they just see + * that we are not in CONSOLE_RUNNING state anymore, or unlock + * other concurrent calls to ConSrvDeleteConsole so that they + * can see that we are in fact already deleting the console. + */ + LeaveCriticalSection(&Console->Lock); + ConSrvUnlockConsoleList(); + + /* FIXME: Send a terminate message to all the processes owning this console */ + + /* Cleanup the UI-oriented part */ + ConioCleanupConsole(Console); + + /*** + * Check that the console is in terminating state before continuing + * (the cleanup code must not change the state of the console... + * ...unless to cancel console deletion ?). + ***/ + + ConSrvLockConsoleListExclusive(); + + /* Re-check the existence of the console, and if it's ok, continue */ + if (!ConSrvValidatePointer(Console)) + { + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); + return; + } + + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE)) + { + ConSrvUnlockConsoleList(); + return; + } + + /* We are in destruction */ + Console->State = CONSOLE_IN_DESTRUCTION; + + /* Remove the console from the list */ + RemoveEntryList(&Console->Entry); + + /* Reset the count to be sure */ + Console->ReferenceCount = 0; + + /* Discard all entries in the input event queue */ + while (!IsListEmpty(&Console->InputBuffer.InputEvents)) + { + CurrentEntry = RemoveHeadList(&Console->InputBuffer.InputEvents); + Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); RtlFreeHeap(ConSrvHeap, 0, Event); }
- ConioCleanupConsole(Console); if (Console->LineBuffer) RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer); while (!IsListEmpty(&Console->HistoryBuffers)) @@ -532,12 +665,22 @@
CloseHandle(Console->InputBuffer.ActiveEvent); if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); - DeleteCriticalSection(&Console->Lock);
RtlFreeUnicodeString(&Console->OriginalTitle); RtlFreeUnicodeString(&Console->Title); IntDeleteAllAliases(Console->Aliases); + + DPRINT1("ConSrvDeleteConsole - Unlocking\n"); + LeaveCriticalSection(&Console->Lock); + DPRINT1("ConSrvDeleteConsole - Destroying lock\n"); + DeleteCriticalSection(&Console->Lock); + DPRINT1("ConSrvDeleteConsole - Lock destroyed ; freeing console\n"); + RtlFreeHeap(ConSrvHeap, 0, Console); + DPRINT1("ConSrvDeleteConsole - Console freed\n"); + + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); }
@@ -545,56 +688,59 @@
CSR_API(SrvOpenConsole) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; PCONSOLE_OPENCONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); + PCONSOLE Console; + + DWORD DesiredAccess = OpenConsoleRequest->Access; + DWORD ShareMode = OpenConsoleRequest->ShareMode; + Object_t *Object;
OpenConsoleRequest->ConsoleHandle = INVALID_HANDLE_VALUE;
+ Status = ConSrvGetConsole(ProcessData, &Console, TRUE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Can't get console\n"); + return Status; + } + RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (ProcessData->Console) - { - DWORD DesiredAccess = OpenConsoleRequest->Access; - DWORD ShareMode = OpenConsoleRequest->ShareMode; - - PCONSOLE Console = ProcessData->Console; - Object_t *Object; - - EnterCriticalSection(&Console->Lock); - - if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT) - { - Object = &Console->ActiveBuffer->Header; - } - else // HANDLE_INPUT - { - Object = &Console->InputBuffer.Header; - } - - if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) || - ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) || - (!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) || - (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0)) - { - DPRINT1("Sharing violation\n"); - Status = STATUS_SHARING_VIOLATION; - } - else - { - Status = ConSrvInsertObject(ProcessData, - &OpenConsoleRequest->ConsoleHandle, - Object, - DesiredAccess, - OpenConsoleRequest->Inheritable, - ShareMode); - } - - LeaveCriticalSection(&Console->Lock); + /* + * Open a handle to either the active screen buffer or the input buffer. + */ + if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT) + { + Object = &Console->ActiveBuffer->Header; + } + else // HANDLE_INPUT + { + Object = &Console->InputBuffer.Header; + } + + if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) || + ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) || + (!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) || + (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0)) + { + DPRINT1("Sharing violation\n"); + Status = STATUS_SHARING_VIOLATION; + } + else + { + Status = ConSrvInsertObject(ProcessData, + &OpenConsoleRequest->ConsoleHandle, + Object, + DesiredAccess, + OpenConsoleRequest->Inheritable, + ShareMode); }
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ ConSrvReleaseConsole(Console, TRUE); return Status; }
@@ -758,7 +904,6 @@
CSR_API(SrvFreeConsole) { - DPRINT1("SrvFreeConsole\n"); ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process)); return STATUS_SUCCESS; } @@ -798,7 +943,6 @@ }
ConSrvReleaseObject(Object, TRUE); - return Status; }
@@ -831,7 +975,6 @@ }
ConSrvReleaseObject(Object, TRUE); - return Status; }
Added: branches/ros-csrss/win32ss/user/consrv/console.h URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/console.h (added) +++ branches/ros-csrss/win32ss/user/consrv/console.h [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -1,0 +1,52 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: win32ss/user/consrv/console.h + * PURPOSE: Consoles Management + * PROGRAMMERS: Hermes Belusca-Maito + */ + +#pragma once + +#define ConSrvLockConsoleListExclusive() \ + RtlAcquireResourceExclusive(&ListLock, TRUE) + +#define ConSrvLockConsoleListShared() \ + RtlAcquireResourceShared(&ListLock, TRUE) + +#define ConSrvUnlockConsoleList() \ + RtlReleaseResource(&ListLock) + +extern LIST_ENTRY ConsoleList; +extern RTL_RESOURCE ListLock; + +#if 0 +/* + * WARNING: Change the state of the console ONLY when the console is locked ! + */ +typedef enum _CONSOLE_STATE +{ + CONSOLE_INITIALIZING, /* Console is initializing */ + CONSOLE_RUNNING , /* Console running */ + CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */ + CONSOLE_IN_DESTRUCTION /* Console in destruction */ +} CONSOLE_STATE, *PCONSOLE_STATE; +#endif + + +VOID WINAPI ConSrvInitConsoleSupport(VOID); +NTSTATUS WINAPI ConSrvInitConsole(OUT PCONSOLE* NewConsole, + IN OUT PCONSOLE_START_INFO ConsoleStartInfo, + IN PCSR_PROCESS ConsoleLeaderProcess); +VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console); +BOOL FASTCALL ConSrvValidatePointer(PCONSOLE Console); +BOOL FASTCALL ConSrvValidateConsoleState(PCONSOLE Console, + CONSOLE_STATE ExpectedState); +BOOL FASTCALL ConSrvValidateConsoleUnsafe(PCONSOLE Console, + CONSOLE_STATE ExpectedState, + BOOL LockConsole); +BOOL FASTCALL ConSrvValidateConsole(PCONSOLE Console, + CONSOLE_STATE ExpectedState, + BOOL LockConsole); + +/* EOF */
Propchange: branches/ros-csrss/win32ss/user/consrv/console.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/ros-csrss/win32ss/user/consrv/consrv.h URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -34,6 +34,9 @@ /* Public Win32K Headers */ #include <ntuser.h>
+/* PSEH for SEH Support */ +#include <pseh/pseh2.h> + /* CSRSS Header */ #include <csr/csrsrv.h>
@@ -91,6 +94,20 @@ LPTHREAD_START_ROUTINE CtrlDispatcher; LPTHREAD_START_ROUTINE PropDispatcher; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS. } CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA; + + +#if 1 // Temporarily put there. +/* + * WARNING: Change the state of the console ONLY when the console is locked ! + */ +typedef enum _CONSOLE_STATE +{ + CONSOLE_INITIALIZING, /* Console is initializing */ + CONSOLE_RUNNING , /* Console running */ + CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */ + CONSOLE_IN_DESTRUCTION /* Console in destruction */ +} CONSOLE_STATE, *PCONSOLE_STATE; +#endif
/* alias.c */ @@ -177,12 +194,12 @@ PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle); -VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData); NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData, struct _CONSOLE** Console, BOOL LockConsole); VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* Console, - BOOL IsConsoleLocked); + BOOL WasConsoleLocked); +VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);
NTSTATUS NTAPI ConSrvNewProcess(PCSR_PROCESS SourceProcess, PCSR_PROCESS TargetProcess);
Modified: branches/ros-csrss/win32ss/user/consrv/guiconsole.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/gu... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/guiconsole.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/guiconsole.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -10,6 +10,7 @@
#include "consrv.h" #include "conio.h" +#include "console.h" #include "settings.h" #include "guiconsole.h" #include "guisettings.h" @@ -212,6 +213,13 @@ GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam) { LRESULT Ret = TRUE; + PCONSOLE Console = GuiData->Console; + + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) + { + Ret = FALSE; + goto Quit; + }
switch (wParam) { @@ -229,7 +237,6 @@
case ID_SYSTEM_EDIT_SELECTALL: { - PCONSOLE Console = GuiData->Console; COORD bottomRight = { 0, 0 };
bottomRight.X = Console->ConsoleSize.X - 1; @@ -255,15 +262,23 @@ break;
default: - Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam); - break; - } + Ret = FALSE; + break; + } + + LeaveCriticalSection(&Console->Lock); + +Quit: + if (!Ret) + Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam); + return Ret; }
static PGUI_CONSOLE_DATA GuiGetGuiData(HWND hWnd) { + /* This function ensures that the console pointer is not NULL */ PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA); return ( ((GuiData == NULL) || (GuiData->hWindow == hWnd && GuiData->Console != NULL)) ? GuiData : NULL ); } @@ -341,6 +356,8 @@ HFONT OldFont; TEXTMETRICW Metrics; SIZE CharSize; + + DPRINT1("GuiConsoleHandleNcCreate\n");
if (NULL == GuiData) { @@ -424,12 +441,7 @@ SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL); GuiConsoleCreateSysMenu(GuiData->hWindow);
- /* Move and resize the window to the user's values */ - GuiConsoleMoveWindow(GuiData); - GuiData->WindowSizeLock = TRUE; - GuiConsoleResizeWindow(GuiData); - GuiData->WindowSizeLock = FALSE; - + DPRINT1("GuiConsoleHandleNcCreate - setting start event\n"); SetEvent(GuiData->hGuiInitEvent);
return (BOOL)DefWindowProcW(GuiData->hWindow, WM_NCCREATE, 0, (LPARAM)Create); @@ -525,8 +537,6 @@ HFONT OldFont;
Buff = Console->ActiveBuffer; - - /// LOCK /// EnterCriticalSection(&Buff->Header.Console->Lock);
TopLine = rc->top / GuiData->CharHeight + Buff->ShowY; BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buff->ShowY; @@ -618,57 +628,71 @@ } }
- /// LOCK /// LeaveCriticalSection(&Buff->Header.Console->Lock); - SelectObject(hDC, OldFont); }
static VOID -GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData, HDC hDCPaint) -{ +GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData) +{ + BOOL Success = TRUE; PCONSOLE Console = GuiData->Console; HDC hDC; PAINTSTRUCT ps;
- if (Console->ActiveBuffer == NULL) return; + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) + { + Success = FALSE; + goto Quit; + } + + if (Console->ActiveBuffer == NULL || + Console->ActiveBuffer->Buffer == NULL) + { + goto Quit; + }
hDC = BeginPaint(GuiData->hWindow, &ps); if (hDC != NULL && ps.rcPaint.left < ps.rcPaint.right && ps.rcPaint.top < ps.rcPaint.bottom) { - if (Console->ActiveBuffer->Buffer != NULL) - { - EnterCriticalSection(&GuiData->Lock); - - GuiConsolePaint(Console, - GuiData, - hDC, - &ps.rcPaint); - - if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) + EnterCriticalSection(&GuiData->Lock); + + GuiConsolePaint(Console, + GuiData, + hDC, + &ps.rcPaint); + + if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) + { + RECT rc; + SmallRectToRect(GuiData, &rc, &Console->Selection.srSelection); + + /* invert the selection */ + if (IntersectRect(&rc, + &ps.rcPaint, + &rc)) { - RECT rc; - SmallRectToRect(GuiData, &rc, &Console->Selection.srSelection); - - /* invert the selection */ - if (IntersectRect(&rc, - &ps.rcPaint, - &rc)) - { - PatBlt(hDC, - rc.left, - rc.top, - rc.right - rc.left, - rc.bottom - rc.top, - DSTINVERT); - } + PatBlt(hDC, + rc.left, + rc.top, + rc.right - rc.left, + rc.bottom - rc.top, + DSTINVERT); } - - LeaveCriticalSection(&GuiData->Lock); - } + } + + LeaveCriticalSection(&GuiData->Lock); } EndPaint(GuiData->hWindow, &ps); + +Quit: + if (Success) + LeaveCriticalSection(&Console->Lock); + else + DefWindowProcW(GuiData->hWindow, WM_PAINT, 0, 0); + + return; }
static VOID @@ -676,6 +700,8 @@ { PCONSOLE Console = GuiData->Console; MSG Message; + + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
Message.hwnd = GuiData->hWindow; Message.message = msg; @@ -689,6 +715,8 @@ }
ConioProcessKey(Console, &Message); + + LeaveCriticalSection(&Console->Lock); }
static VOID @@ -705,6 +733,8 @@ PCONSOLE_SCREEN_BUFFER Buff;
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL); + + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
Buff = Console->ActiveBuffer; GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y); @@ -782,14 +812,15 @@ GuiData->OldCursor.y = Buff->CursorPosition.Y; } } + + LeaveCriticalSection(&Console->Lock); }
static VOID GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData) { PCONSOLE Console = GuiData->Console; - - /// LOCK /// EnterCriticalSection(&Console->Lock); + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
/* * FIXME: Windows will wait up to 5 seconds for the thread to exit. @@ -798,17 +829,23 @@ */ ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
- /// LOCK /// LeaveCriticalSection(&Console->Lock); -} - -static VOID -GuiConsoleHandleNcDestroy(PGUI_CONSOLE_DATA GuiData) -{ - KillTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER); - GetSystemMenu(GuiData->hWindow, TRUE); - - SetWindowLongPtrW(GuiData->hWindow, GWLP_USERDATA, (DWORD_PTR)NULL); - GuiData->hWindow = NULL; + LeaveCriticalSection(&Console->Lock); +} + +static LRESULT +GuiConsoleHandleNcDestroy(HWND hWnd) +{ + // PGUI_CONSOLE_DATA GuiData; + + KillTimer(hWnd, CONGUI_UPDATE_TIMER); + GetSystemMenu(hWnd, TRUE); + + /* Free the GuiData registration */ + SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL); + // GuiData->hWindow = NULL; + + // return 0; + return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0); }
static COORD @@ -835,43 +872,85 @@ return Coord; }
-static VOID -GuiConsoleLeftMouseDown(PGUI_CONSOLE_DATA GuiData, LPARAM lParam) -{ +static LRESULT +GuiConsoleHandleMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT Ret = TRUE; PCONSOLE Console = GuiData->Console;
- Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam); - SetCapture(GuiData->hWindow); - Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN; - GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor); -} - -static VOID -GuiConsoleLeftMouseUp(PGUI_CONSOLE_DATA GuiData, LPARAM lParam) -{ - PCONSOLE Console = GuiData->Console; - COORD c; - - if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return; - - c = PointToCoord(GuiData, lParam); - Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN; - GuiConsoleUpdateSelection(Console, &c); - ReleaseCapture(); -} - -static VOID -GuiConsoleMouseMove(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam) -{ - PCONSOLE Console = GuiData->Console; - COORD c; - - if (!(wParam & MK_LBUTTON)) return; - - if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return; - - c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */ - GuiConsoleUpdateSelection(Console, &c); + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) + { + Ret = FALSE; + goto Quit; + } + + switch (msg) + { + case WM_LBUTTONDOWN: + { + Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam); + SetCapture(GuiData->hWindow); + Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN; + GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor); + break; + } + + case WM_LBUTTONUP: + { + COORD c; + + if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break; + + c = PointToCoord(GuiData, lParam); + Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN; + GuiConsoleUpdateSelection(Console, &c); + ReleaseCapture(); + + break; + } + + case WM_RBUTTONDOWN: + { + if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)) + { + GuiConsolePaste(GuiData); + } + else + { + GuiConsoleCopy(GuiData); + + /* Clear the selection */ + GuiConsoleUpdateSelection(Console, NULL); + } + + break; + } + + case WM_MOUSEMOVE: + { + COORD c; + + if (!(wParam & MK_LBUTTON)) break; + if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break; + + c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */ + GuiConsoleUpdateSelection(Console, &c); + + break; + } + + default: + Ret = FALSE; + break; + } + + LeaveCriticalSection(&Console->Lock); + +Quit: + if (!Ret) + Ret = DefWindowProcW(GuiData->hWindow, msg, wParam, lParam); + + return Ret; }
static VOID @@ -983,29 +1062,13 @@ }
static VOID -GuiConsoleRightMouseDown(PGUI_CONSOLE_DATA GuiData) -{ - PCONSOLE Console = GuiData->Console; - - if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)) - { - GuiConsolePaste(GuiData); - } - else - { - GuiConsoleCopy(GuiData); - - /* Clear the selection */ - GuiConsoleUpdateSelection(Console, NULL); - } -} - -static VOID GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo) { PCONSOLE Console = GuiData->Console; DWORD windx, windy;
+ if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return; + windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)); windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
@@ -1020,12 +1083,16 @@
minMaxInfo->ptMaxTrackSize.x = windx; minMaxInfo->ptMaxTrackSize.y = windy; + + LeaveCriticalSection(&Console->Lock); }
static VOID GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam) { PCONSOLE Console = GuiData->Console; + + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
if ((GuiData->WindowSizeLock == FALSE) && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED)) @@ -1076,6 +1143,8 @@
GuiData->WindowSizeLock = FALSE; } + + LeaveCriticalSection(&Console->Lock); }
/* @@ -1107,8 +1176,7 @@ } */
-static -LRESULT +static LRESULT GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam) { PCONSOLE Console = GuiData->Console; @@ -1118,7 +1186,7 @@ int old_pos, Maximum; PUSHORT pShowXY;
- if (GuiData == NULL) return FALSE; + if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
Buff = Console->ActiveBuffer;
@@ -1139,10 +1207,7 @@ sInfo.cbSize = sizeof(SCROLLINFO); sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
- if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo)) - { - return FALSE; - } + if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo)) goto Quit;
old_pos = sInfo.nPos;
@@ -1209,6 +1274,8 @@ UpdateWindow(GuiData->hWindow); }
+Quit: + LeaveCriticalSection(&Console->Lock); return 0; }
@@ -1217,14 +1284,21 @@ { LRESULT Result = 0; PGUI_CONSOLE_DATA GuiData = NULL; + PCONSOLE Console = NULL;
/* - * If it's the first time we create a window - * for the terminal, just initialize it. + * - If it's the first time we create a window for the terminal, + * just initialize it and return. + * + * - If we are destroying the window, just do it and return. */ if (msg == WM_NCCREATE) { return (LRESULT)GuiConsoleHandleNcCreate(hWnd, (LPCREATESTRUCTW)lParam); + } + else if (msg == WM_NCDESTROY) + { + return GuiConsoleHandleNcDestroy(hWnd); }
/* @@ -1235,24 +1309,20 @@ GuiData = GuiGetGuiData(hWnd); if (GuiData == NULL) return 0;
- // TODO: If the console is about to be destroyed, leave the loop. - - /* Lock the console */ - EnterCriticalSection(&GuiData->Console->Lock); - - /* We have a console, start message dispatching. */ + /* + * Each helper function which needs the console + * has to validate and lock it. + */ + + /* We have a console, start message dispatching */ switch (msg) { case WM_CLOSE: GuiConsoleHandleClose(GuiData); break;
- case WM_NCDESTROY: - GuiConsoleHandleNcDestroy(GuiData); - break; - case WM_PAINT: - GuiConsoleHandlePaint(GuiData, (HDC)wParam); + GuiConsoleHandlePaint(GuiData); break;
case WM_KEYDOWN: @@ -1260,37 +1330,43 @@ case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_CHAR: + { GuiConsoleHandleKey(GuiData, msg, wParam, lParam); break; + }
case WM_TIMER: GuiConsoleHandleTimer(GuiData); break;
+ case WM_MOUSEMOVE: case WM_LBUTTONDOWN: - GuiConsoleLeftMouseDown(GuiData, lParam); - break; - case WM_LBUTTONUP: - GuiConsoleLeftMouseUp(GuiData, lParam); - break; - + case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: - GuiConsoleRightMouseDown(GuiData); - break; - - case WM_MOUSEMOVE: - GuiConsoleMouseMove(GuiData, wParam, lParam); - break; + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MOUSEWHEEL: + { + Result = GuiConsoleHandleMouse(GuiData, msg, wParam, lParam); + break; + }
case WM_SYSCOMMAND: + { Result = GuiConsoleHandleSysMenuCommand(GuiData, wParam, lParam); break; + }
case WM_HSCROLL: case WM_VSCROLL: + { Result = GuiConsoleHandleScroll(GuiData, msg, wParam); break; + }
case WM_GETMINMAXINFO: GuiConsoleGetMinMaxInfo(GuiData, (PMINMAXINFO)lParam); @@ -1301,25 +1377,29 @@ break;
case PM_APPLY_CONSOLE_INFO: - GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam); - break; + { + Console = GuiData->Console; // Not NULL because checked in GuiGetGuiData. + if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) + { + GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam); + LeaveCriticalSection(&Console->Lock); + } + break; + }
case PM_CONSOLE_BEEP: DPRINT1("Beep !!\n"); Beep(800, 200); break;
- case PM_CONSOLE_SET_TITLE: - SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer); - break; + // case PM_CONSOLE_SET_TITLE: + // SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer); + // break;
default: - Result = DefWindowProcW(GuiData->hWindow, msg, wParam, lParam); - break; - } - - /* Unlock the console */ - LeaveCriticalSection(&GuiData->Console->Lock); + Result = DefWindowProcW(hWnd, msg, wParam, lParam); + break; + }
return Result; } @@ -1336,8 +1416,6 @@ HWND NewWindow; LONG WindowCount; MSG Msg; - PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam; - PCONSOLE Console = GuiData->Console;
switch (msg) { @@ -1349,6 +1427,9 @@
case PM_CREATE_CONSOLE: { + PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam; + PCONSOLE Console = GuiData->Console; + NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE, GUI_CONSOLE_WINDOW_CLASS, Console->Title.Buffer, @@ -1381,7 +1462,16 @@ SendMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm); }
- ShowWindow(NewWindow, (int)wParam); + /* Move and resize the window to the user's values */ + /* CAN WE DEADLOCK ?? */ + GuiConsoleMoveWindow(GuiData); + GuiData->WindowSizeLock = TRUE; + GuiConsoleResizeWindow(GuiData); + GuiData->WindowSizeLock = FALSE; + + // ShowWindow(NewWindow, (int)wParam); + ShowWindowAsync(NewWindow, (int)wParam); + DPRINT1("Window showed\n"); }
return (LRESULT)NewWindow; @@ -1389,16 +1479,20 @@
case PM_DESTROY_CONSOLE: { + PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam; + /* * Window creation is done using a PostMessage(), so it's possible * that the window that we want to destroy doesn't exist yet. * So first empty the message queue. */ + /* while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); - } + }*/ + while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) ;
if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */ { @@ -1607,6 +1701,8 @@ Console->TermIFace.Data = NULL; DeleteCriticalSection(&GuiData->Lock); RtlFreeHeap(ConSrvHeap, 0, GuiData); + + DPRINT1("Quit GuiCleanupConsole\n"); }
static VOID WINAPI @@ -1835,7 +1931,8 @@ GuiChangeTitle(PCONSOLE Console) { PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data; - PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0); + // PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0); + SetWindowText(GuiData->hWindow, Console->Title.Buffer); }
static BOOL WINAPI @@ -1916,6 +2013,7 @@ { PGUI_CONSOLE_DATA GuiData; GUI_CONSOLE_INFO TermInfo; + SIZE_T Length = 0;
if (Console == NULL || ConsoleInfo == NULL) return STATUS_INVALID_PARAMETER; @@ -1984,7 +2082,9 @@ * Set up the GUI data */
+ Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE); + GuiData->GuiInfo.FaceName[Length] = L'\0'; GuiData->GuiInfo.FontFamily = TermInfo.FontFamily; GuiData->GuiInfo.FontSize = TermInfo.FontSize; GuiData->GuiInfo.FontWeight = TermInfo.FontWeight; @@ -2034,6 +2134,7 @@
/* Wait until initialization has finished */ WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE); + DPRINT1("OK we created the console window\n"); CloseHandle(GuiData->hGuiInitEvent); GuiData->hGuiInitEvent = NULL;
Modified: branches/ros-csrss/win32ss/user/consrv/guisettings.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/gu... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/guisettings.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/guisettings.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -86,7 +86,9 @@
if (!wcscmp(szValueName, L"FaceName")) { + SIZE_T Length = min(wcslen(szValue) + 1, LF_FACESIZE); // wcsnlen wcsncpy(TermInfo->FaceName, szValue, LF_FACESIZE); + TermInfo->FaceName[Length] = L'\0'; RetVal = TRUE; } else if (!wcscmp(szValueName, L"FontFamily")) @@ -150,7 +152,7 @@ return FALSE; }
- SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); + SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); // wcsnlen SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE); SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0); SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE); @@ -269,43 +271,59 @@ pSharedInfo->hConsoleWindow = GuiData->hWindow; pSharedInfo->ShowDefaultParams = Defaults;
- /* Console information */ - pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize; - pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; - pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup; - pSharedInfo->ci.FullScreen = Console->FullScreen; - pSharedInfo->ci.QuickEdit = Console->QuickEdit; - pSharedInfo->ci.InsertMode = Console->InsertMode; - pSharedInfo->ci.InputBufferSize = 0; - pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize; - pSharedInfo->ci.ConsoleSize = Console->ConsoleSize; - pSharedInfo->ci.CursorBlinkOn; - pSharedInfo->ci.ForceCursorOff; - pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize; - pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib; - pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib; - pSharedInfo->ci.CodePage; - - /* GUI Information */ - pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO); - GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1); - wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); - GuiInfo->FontSize = (DWORD)GuiData->GuiInfo.FontSize; - GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight; - GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts; - /// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition; - GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; - GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin; - /* Offsetize */ - pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo); - - /* Palette */ - memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors)); - - /* Title of the console, original one corresponding to the one set by the console leader */ - Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1, - Console->OriginalTitle.Length / sizeof(WCHAR)); - wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); + /* + * We fill-in the fields only if we display + * our properties, not the default ones. + */ + if (!Defaults) + { + /* Console information */ + pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize; + pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; + pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup; + pSharedInfo->ci.FullScreen = Console->FullScreen; + pSharedInfo->ci.QuickEdit = Console->QuickEdit; + pSharedInfo->ci.InsertMode = Console->InsertMode; + pSharedInfo->ci.InputBufferSize = 0; + pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize; + pSharedInfo->ci.ConsoleSize = Console->ConsoleSize; + pSharedInfo->ci.CursorBlinkOn; + pSharedInfo->ci.ForceCursorOff; + pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize; + pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib; + pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib; + pSharedInfo->ci.CodePage; + + /* GUI Information */ + pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO); + GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1); + Length = min(wcslen(GuiData->GuiInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen + wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); + GuiInfo->FaceName[Length] = L'\0'; + GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily; + GuiInfo->FontSize = GuiData->GuiInfo.FontSize; + GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight; + GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts; + /// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition; + GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; + GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin; + /* Offsetize */ + pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo); + + /* Palette */ + memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors)); + + /* Title of the console, original one corresponding to the one set by the console leader */ + Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1, + Console->OriginalTitle.Length / sizeof(WCHAR)); + wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); + } + else + { + Length = 0; + } + + /* Null-terminate the title */ pSharedInfo->ci.ConsoleTitle[Length] = L'\0';
@@ -326,29 +344,46 @@ if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status); - NtClose(hSection); - return; + goto Quit; }
/* Start the properties dialog */ if (ProcessData->PropDispatcher) { - HANDLE Thread; - - Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, - ProcessData->PropDispatcher, - (PVOID)hClientSection, 0, NULL); - if (NULL == Thread) - { - DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); - return; - } - - DPRINT1("We succeeded at creating ProcessData->PropDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); - /// WaitForSingleObject(Thread, INFINITE); - CloseHandle(Thread); - } - + _SEH2_TRY + { + HANDLE Thread = NULL; + + _SEH2_TRY + { + Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, + ProcessData->PropDispatcher, + (PVOID)hClientSection, 0, NULL); + if (NULL == Thread) + { + DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); + } + else + { + DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); + /// WaitForSingleObject(Thread, INFINITE); + } + } + _SEH2_FINALLY + { + CloseHandle(Thread); + } + _SEH2_END; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = %08X\n", Status); + } + _SEH2_END; + } + +Quit: /* We have finished, close the section handle */ NtClose(hSection); return; @@ -369,8 +404,6 @@ PTERMINAL_INFO TermInfo = NULL; PGUI_CONSOLE_INFO GuiInfo = NULL;
- /// LOCK /// EnterCriticalSection(&Console->Lock); - /* Get the console leader process, our client */ ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink, CONSOLE_PROCESS_DATA, @@ -406,51 +439,65 @@ return Status; }
- /* Check that the section is well-sized */ - if ( (ViewSize < sizeof(CONSOLE_PROPS)) || - (pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) || - (ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) ) - { - DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n"); - Status = STATUS_INVALID_VIEW_SIZE; - goto Quit; - } - - // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow - - /* Set the console informations */ - ConInfo = &pConInfo->ci; - ConSrvApplyUserSettings(Console, ConInfo); - - /* Set the terminal informations - De-offsetization of the pointer */ - TermInfo = &pConInfo->TerminalInfo; - GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo); - - // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO)); - - /* Move the window to the user's values */ - GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition; - GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin; - GuiConsoleMoveWindow(GuiData); - - InvalidateRect(GuiData->hWindow, NULL, TRUE); - - - /* - * Save settings if needed - */ - - // FIXME: Do it in the console properties applet ?? - if (SaveSettings) - { - DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); - ConSrvWriteUserSettings(ConInfo, ProcessId); - GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId); - } - - Status = STATUS_SUCCESS; - - /// LOCK /// LeaveCriticalSection(&Console->Lock); + _SEH2_TRY + { + /* Check that the section is well-sized */ + if ( (ViewSize < sizeof(CONSOLE_PROPS)) || + (pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) || + (ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) ) + { + DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n"); + Status = STATUS_INVALID_VIEW_SIZE; + _SEH2_YIELD(goto Quit); + } + + // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow + + /* Retrieve terminal informations */ + ConInfo = &pConInfo->ci; + TermInfo = &pConInfo->TerminalInfo; + GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo); + + /* + * If we don't set the default parameters, + * apply them, otherwise just save them. + */ + if (pConInfo->ShowDefaultParams == FALSE) + { + /* Set the console informations */ + ConSrvApplyUserSettings(Console, ConInfo); + + /* Set the terminal informations */ + + // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO)); + + /* Move the window to the user's values */ + GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition; + GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin; + GuiConsoleMoveWindow(GuiData); + + InvalidateRect(GuiData->hWindow, NULL, TRUE); + } + + /* + * Save settings if needed + */ + // FIXME: Do it in the console properties applet ?? + if (SaveSettings) + { + DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); + ConSrvWriteUserSettings(ConInfo, ProcessId); + GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId); + } + + Status = STATUS_SUCCESS; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status); + } + _SEH2_END;
Quit: /* Finally, close the section and return */
Modified: branches/ros-csrss/win32ss/user/consrv/handle.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/ha... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -10,8 +10,9 @@
#include "consrv.h" #include "conio.h" - -//#define NDEBUG +#include "console.h" + +#define NDEBUG #include <debug.h>
@@ -22,7 +23,7 @@ { Object_t *Object = Entry->Object;
- DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type); + DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change; if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change; @@ -236,8 +237,6 @@ static VOID ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData) { - DPRINT1("ConSrvFreeHandlesTable\n"); - RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if (ProcessData->HandleTable != NULL) @@ -267,12 +266,13 @@ BOOL Inheritable, DWORD ShareMode) { -#define IO_HANDLES_INCREMENT 2*3 +#define IO_HANDLES_INCREMENT 2 * 3
ULONG i; PCONSOLE_IO_HANDLE Block;
- RtlEnterCriticalSection(&ProcessData->HandleTableLock); + // NOTE: Commented out because calling code always lock HandleTableLock before. + // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
for (i = 0; i < ProcessData->HandleTableSize; i++) { @@ -289,7 +289,7 @@ IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE)); if (Block == NULL) { - RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); return STATUS_UNSUCCESSFUL; } RtlCopyMemory(Block, @@ -307,7 +307,7 @@ ConSrvCreateHandleEntry(&ProcessData->HandleTable[i]); *Handle = ULongToHandle((i << 2) | 0x3);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS; } @@ -329,11 +329,9 @@ return STATUS_INVALID_HANDLE; }
- DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]); ConSrvCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - return STATUS_SUCCESS; }
@@ -376,16 +374,24 @@ return STATUS_INVALID_HANDLE; }
- _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- if (LockConsole) EnterCriticalSection(&ObjectEntry->Console->Lock); - - /* Return the objects to the caller */ - *Object = ObjectEntry; - if (Entry) *Entry = HandleEntry; - - return STATUS_SUCCESS; + if (ConSrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole)) + { + _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount); + + /* Return the objects to the caller */ + *Object = ObjectEntry; + if (Entry) *Entry = HandleEntry; + + // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + return STATUS_SUCCESS; + } + else + { + // RtlLeaveCriticalSection(&ProcessData->HandleTableLock); + return STATUS_INVALID_HANDLE; + } }
VOID @@ -464,6 +470,13 @@ PHANDLE pErrorHandle) { NTSTATUS Status = STATUS_SUCCESS; + + /* Validate and lock the console */ + if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE)) + { + // FIXME: Find another status code + return STATUS_UNSUCCESSFUL; + }
/* Inherit the console */ ProcessData->Console = Console; @@ -479,7 +492,7 @@ { DPRINT1("Failed to initialize the handles table\n"); ProcessData->Console = NULL; - return Status; + goto Quit; } }
@@ -494,7 +507,7 @@ DPRINT1("NtDuplicateObject() failed: %lu\n", Status); ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table. ProcessData->Console = NULL; - return Status; + goto Quit; }
/* Insert the process into the processes list of the console */ @@ -506,29 +519,34 @@ /* Update the internal info of the terminal */ ConioRefreshInternalInfo(ProcessData->Console);
- return STATUS_SUCCESS; + Status = STATUS_SUCCESS; + +Quit: + /* Unlock the console and return */ + LeaveCriticalSection(&Console->Lock); + return Status; }
VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) { - PCONSOLE Console; + PCONSOLE Console = ProcessData->Console;
DPRINT1("ConSrvRemoveConsole\n");
- /* Close all console handles and free the handle table memory */ - ConSrvFreeHandlesTable(ProcessData); - - /* Detach process from console */ - Console = ProcessData->Console; - if (Console != NULL) - { - DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount); + RtlEnterCriticalSection(&ProcessData->HandleTableLock); + + /* Validate and lock the console */ + if (ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE)) + { + DPRINT1("ConSrvRemoveConsole - Locking OK\n"); + + /* Close all console handles and free the handles table */ + ConSrvFreeHandlesTable(ProcessData); + + /* Detach the process from the console */ ProcessData->Console = NULL; - - EnterCriticalSection(&Console->Lock); - DPRINT1("ConSrvRemoveConsole - Locking OK\n");
/* Remove ourselves from the console's list of processes */ RemoveEntryList(&ProcessData->ConsoleLink); @@ -537,10 +555,105 @@ ConioRefreshInternalInfo(Console);
/* Release the console */ + DPRINT1("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount); ConSrvReleaseConsole(Console, TRUE); //CloseHandle(ProcessData->ConsoleEvent); //ProcessData->ConsoleEvent = NULL; } + + RtlLeaveCriticalSection(&ProcessData->HandleTableLock); +} + +BOOL +FASTCALL +ConSrvValidatePointer(PCONSOLE Console) +{ + PLIST_ENTRY ConsoleEntry; + PCONSOLE CurrentConsole = NULL; + + if (!Console) return FALSE; + + /* The console list must be locked */ + // ASSERT(Console_list_locked); + + ConsoleEntry = ConsoleList.Flink; + while (ConsoleEntry != &ConsoleList) + { + CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry); + ConsoleEntry = ConsoleEntry->Flink; + if (CurrentConsole == Console) return TRUE; + } + + return FALSE; +} + +BOOL +FASTCALL +ConSrvValidateConsoleState(PCONSOLE Console, + CONSOLE_STATE ExpectedState) +{ + // if (!Console) return FALSE; + + /* The console must be locked */ + // ASSERT(Console_locked); + + return (Console->State == ExpectedState); +} + +BOOL +FASTCALL +ConSrvValidateConsoleUnsafe(PCONSOLE Console, + CONSOLE_STATE ExpectedState, + BOOL LockConsole) +{ + if (!Console) return FALSE; + + /* + * Lock the console to forbid possible console's state changes + * (which must be done when the console is already locked). + * If we don't want to lock it, it's because the lock is already + * held. So there must be no problems. + */ + if (LockConsole) EnterCriticalSection(&Console->Lock); + + // ASSERT(Console_locked); + + /* Check whether the console's state is what we expect */ + if (!ConSrvValidateConsoleState(Console, ExpectedState)) + { + if (LockConsole) LeaveCriticalSection(&Console->Lock); + return FALSE; + } + + return TRUE; +} + +BOOL +FASTCALL +ConSrvValidateConsole(PCONSOLE Console, + CONSOLE_STATE ExpectedState, + BOOL LockConsole) +{ + BOOL RetVal = FALSE; + + if (!Console) return FALSE; + + /* + * Forbid creation or deletion of consoles when + * checking for the existence of a console. + */ + ConSrvLockConsoleListShared(); + + if (ConSrvValidatePointer(Console)) + { + RetVal = ConSrvValidateConsoleUnsafe(Console, + ExpectedState, + LockConsole); + } + + /* Unlock the console list and return */ + ConSrvUnlockConsoleList(); + return RetVal; }
NTSTATUS @@ -549,37 +662,53 @@ PCONSOLE* Console, BOOL LockConsole) { + NTSTATUS Status = STATUS_SUCCESS; PCONSOLE ProcessConsole;
RtlEnterCriticalSection(&ProcessData->HandleTableLock); ProcessConsole = ProcessData->Console;
- if (!ProcessConsole) + if (ConSrvValidateConsole(ProcessConsole, CONSOLE_RUNNING, LockConsole)) + { + InterlockedIncrement(&ProcessConsole->ReferenceCount); + *Console = ProcessConsole; + } + else { *Console = NULL; - RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - return STATUS_INVALID_HANDLE; - } - - InterlockedIncrement(&ProcessConsole->ReferenceCount); + Status = STATUS_INVALID_HANDLE; + } + RtlLeaveCriticalSection(&ProcessData->HandleTableLock); - - if (LockConsole) EnterCriticalSection(&ProcessConsole->Lock); - - *Console = ProcessConsole; - - return STATUS_SUCCESS; + return Status; }
VOID FASTCALL ConSrvReleaseConsole(PCONSOLE Console, - BOOL IsConsoleLocked) -{ - if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock); - - /* Decrement reference count */ - if (_InterlockedDecrement(&Console->ReferenceCount) == 0) - ConSrvDeleteConsole(Console); + BOOL 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); }
NTSTATUS @@ -745,8 +874,6 @@ * This function is called whenever a new process (GUI or CUI) is destroyed. **************************************************************************/
- DPRINT1("ConSrvDisconnect\n"); - if ( ProcessData->Console != NULL || ProcessData->HandleTable != NULL ) { @@ -828,6 +955,7 @@ } }
+ /* Insert the new handle inside the process handles table */ ApiMessage->Status = ConSrvInsertObject(ProcessData, &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value! Entry->Object,
Modified: branches/ros-csrss/win32ss/user/consrv/init.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/in... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] Sat Mar 30 18:44:56 2013 @@ -10,6 +10,7 @@
#include "consrv.h" #include "conio.h" +#include "console.h"
#define NDEBUG #include <debug.h>