NTSTATUS NTAPI ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer) { if (Console == NULL || Buffer == NULL) return STATUS_INVALID_PARAMETER; /* Validity check */ ASSERT(Console == Buffer->Header.Console); if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS; /* If old buffer has no handles, it's now unreferenced */ if (Console->ActiveBuffer->Header.ReferenceCount == 0) { ConDrvDeleteScreenBuffer(Console->ActiveBuffer); } /* Tie console to new buffer and signal the change to the frontend */ ConioSetActiveScreenBuffer(Buffer); return STATUS_SUCCESS; }
static VOID ConSrvCloseHandle(IN PCONSOLE_IO_HANDLE Handle) { PCONSOLE_IO_OBJECT Object = Handle->Object; if (Object != NULL) { /* * If this is a input handle, notify and dereference * all the waits related to this handle. */ if (Object->Type == INPUT_BUFFER) { // PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; PCONSOLE Console = Object->Console; /* * 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(&Console->ReadWaitQueue, TRUE, NULL, (PVOID)Handle); if (!IsListEmpty(&Console->ReadWaitQueue)) { CsrDereferenceWait(&Console->ReadWaitQueue); } } /* If the last handle to a screen buffer is closed, delete it... */ if (AdjustHandleCounts(Handle, -1) == 0) { if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER) { PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object; /* ...unless it's the only buffer left. Windows allows deletion * even of the last buffer, but having to deal with a lack of * any active buffer might be error-prone. */ if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink) ConDrvDeleteScreenBuffer(Buffer); } else if (Object->Type == INPUT_BUFFER) { DPRINT("Closing the input buffer\n"); } else { DPRINT1("Invalid object type %d\n", Object->Type); } } /* Invalidate (zero-out) this handle entry */ // Handle->Object = NULL; // RtlZeroMemory(Handle, sizeof(*Handle)); } RtlZeroMemory(Handle, sizeof(*Handle)); // Be sure the whole entry is invalidated. }
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console) { DPRINT("ConDrvDeleteConsole(0x%p)\n", Console); /* * Forbid validation of any console by other threads * during the deletion of this console. */ ConDrvLockConsoleListExclusive(); /* * If the console is already being destroyed, i.e. not running * or finishing to be initialized, just return. */ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE) && !ConDrvValidateConsoleUnsafe(Console, CONSOLE_INITIALIZING, TRUE)) { /* Unlock the console list and return */ ConDrvUnlockConsoleList(); 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 * ConDrvValidateConsoleUnsafe functions so that they just see * that we are not in CONSOLE_RUNNING state anymore, or unlock * other concurrent calls to ConDrvDeleteConsole so that they * can see that we are in fact already deleting the console. */ LeaveCriticalSection(&Console->Lock); ConDrvUnlockConsoleList(); /* Deregister the terminal */ DPRINT("Deregister terminal\n"); ConDrvDetachTerminal(Console); DPRINT("Terminal deregistered\n"); /*** * 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 ?). ***/ ConDrvLockConsoleListExclusive(); if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE)) { ConDrvUnlockConsoleList(); return; } /* We are now in destruction */ Console->State = CONSOLE_IN_DESTRUCTION; /* We really delete the console. Reset the count to be sure. */ Console->ReferenceCount = 0; /* Remove the console from the list */ RemoveConsole(Console); /* Delete the last screen buffer */ ConDrvDeleteScreenBuffer(Console->ActiveBuffer); Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) { /***ConDrvUnlockConsoleList();***/ ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE); } /* Deinitialize the input buffer */ ConDrvDeinitInputBuffer(Console); if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); DPRINT("ConDrvDeleteConsole - Unlocking\n"); LeaveCriticalSection(&Console->Lock); DPRINT("ConDrvDeleteConsole - Destroying lock\n"); DeleteCriticalSection(&Console->Lock); DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n"); ConsoleFreeHeap(Console); DPRINT("ConDrvDeleteConsole - Console destroyed\n"); /* Unlock the console list and return */ ConDrvUnlockConsoleList(); }