VOID GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer) { PGRAPHICS_SCREEN_BUFFER Buff = (PGRAPHICS_SCREEN_BUFFER)Buffer; /* * IMPORTANT !! Reinitialize the type so that we don't enter a recursive * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy. */ Buffer->Header.Type = SCREEN_BUFFER; /* * Uninitialize the graphics screen buffer * in the reverse way we initialized it. */ NtUnmapViewOfSection(Buff->ClientProcess, Buff->ClientBitMap); NtUnmapViewOfSection(NtCurrentProcess(), Buff->BitMap); NtClose(Buff->hSection); NtDuplicateObject(Buff->ClientProcess, Buff->ClientMutex, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE); NtClose(Buff->Mutex); ConsoleFreeHeap(Buff->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy(Buffer); }
NTSTATUS TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN PCONSOLE Console, IN HANDLE ProcessHandle, IN PTEXTMODE_BUFFER_INFO TextModeInfo) { NTSTATUS Status = STATUS_SUCCESS; PTEXTMODE_SCREEN_BUFFER NewBuffer = NULL; UNREFERENCED_PARAMETER(ProcessHandle); if (Console == NULL || Buffer == NULL || TextModeInfo == NULL) return STATUS_INVALID_PARAMETER; *Buffer = NULL; Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer, Console, &TextVtbl, sizeof(TEXTMODE_SCREEN_BUFFER)); if (!NT_SUCCESS(Status)) return Status; NewBuffer->Header.Type = TEXTMODE_BUFFER; NewBuffer->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, TextModeInfo->ScreenBufferSize.X * TextModeInfo->ScreenBufferSize.Y * sizeof(CHAR_INFO)); if (NewBuffer->Buffer == NULL) { CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); return STATUS_INSUFFICIENT_RESOURCES; } NewBuffer->ScreenBufferSize = NewBuffer->OldScreenBufferSize = TextModeInfo->ScreenBufferSize; NewBuffer->ViewSize = NewBuffer->OldViewSize = Console->ConsoleSize; NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0; NewBuffer->VirtualY = 0; NewBuffer->CursorBlinkOn = NewBuffer->ForceCursorOff = FALSE; NewBuffer->CursorInfo.bVisible = (TextModeInfo->IsCursorVisible && (TextModeInfo->CursorSize != 0)); NewBuffer->CursorInfo.dwSize = min(max(TextModeInfo->CursorSize, 0), 100); NewBuffer->ScreenDefaultAttrib = TextModeInfo->ScreenAttrib; NewBuffer->PopupDefaultAttrib = TextModeInfo->PopupAttrib; /* Initialize buffer to be empty with default attributes */ for (NewBuffer->CursorPosition.Y = 0 ; NewBuffer->CursorPosition.Y < NewBuffer->ScreenBufferSize.Y; NewBuffer->CursorPosition.Y++) { ClearLineBuffer(NewBuffer); } NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0; NewBuffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer; return STATUS_SUCCESS; }
VOID TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer) { PTEXTMODE_SCREEN_BUFFER Buff = (PTEXTMODE_SCREEN_BUFFER)Buffer; /* * IMPORTANT !! Reinitialize the type so that we don't enter a recursive * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy. */ Buffer->Header.Type = SCREEN_BUFFER; ConsoleFreeHeap(Buff->Buffer); CONSOLE_SCREEN_BUFFER_Destroy(Buffer); }
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) { PCONSOLE Console = Buffer->Header.Console; PCONSOLE_SCREEN_BUFFER NewBuffer; RemoveEntryList(&Buffer->ListEntry); if (Buffer == Console->ActiveBuffer) { /* Delete active buffer; switch to most recently created */ Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) { NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CONSOLE_SCREEN_BUFFER, ListEntry); ConioSetActiveScreenBuffer(NewBuffer); } } CONSOLE_SCREEN_BUFFER_Destroy(Buffer); }
VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) { PCONSOLE Console = Buffer->Header.Console; PCONSOLE_SCREEN_BUFFER NewBuffer; /* * We should notify temporarily the frontend because we are susceptible * to delete the screen buffer it is using (which may be different from * the active screen buffer in some cases), and because, if it actually * uses the active screen buffer, we are going to nullify its pointer to * change it. */ TermReleaseScreenBuffer(Console, Buffer); RemoveEntryList(&Buffer->ListEntry); if (Buffer == Console->ActiveBuffer) { /* Delete active buffer; switch to most recently created */ if (!IsListEmpty(&Console->BufferList)) { NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CONSOLE_SCREEN_BUFFER, ListEntry); /* Tie console to new buffer and signal the change to the frontend */ ConioSetActiveScreenBuffer(NewBuffer); } else { Console->ActiveBuffer = NULL; // InterlockedExchangePointer(&Console->ActiveBuffer, NULL); } } CONSOLE_SCREEN_BUFFER_Destroy(Buffer); }
NTSTATUS GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, IN PGRAPHICS_BUFFER_INFO GraphicsInfo) { NTSTATUS Status = STATUS_SUCCESS; PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; HANDLE ProcessHandle; if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL) return STATUS_INVALID_PARAMETER; *Buffer = NULL; Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer, Console, sizeof(GRAPHICS_SCREEN_BUFFER)); if (!NT_SUCCESS(Status)) return Status; NewBuffer->Header.Type = GRAPHICS_BUFFER; NewBuffer->Vtbl = &GraphicsVtbl; /* * Remember the handle to the process so that we can close or unmap * correctly the allocated resources when the client releases the * screen buffer. */ ProcessHandle = CsrGetClientThread()->Process->ProcessHandle; NewBuffer->ClientProcess = ProcessHandle; /* Get infos from the graphics buffer information structure */ NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength; NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength); if (NewBuffer->BitMapInfo == NULL) { CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); return STATUS_INSUFFICIENT_RESOURCES; } /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0) GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight; /* We do not use anything else than uncompressed bitmaps */ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB) { DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression); GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB; } RtlCopyMemory(NewBuffer->BitMapInfo, GraphicsInfo->Info.lpBitMapInfo, GraphicsInfo->Info.dwBitMapInfoLength); NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage; /* Set the screen buffer size. Fight against overflows. */ if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF && -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF ) { /* Be careful about the sign of biHeight */ NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ; NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight; NewBuffer->OldViewSize = NewBuffer->ViewSize = NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize; } else { Status = STATUS_INSUFFICIENT_RESOURCES; ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a mutex to synchronize bitmap memory access * between ourselves and the client. */ Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateMutant() failed: %lu\n", Status); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Duplicate the Mutex for the client. We must keep a trace of it * so that we can close it when the client releases the screen buffer. */ Status = NtDuplicateObject(NtCurrentProcess(), NewBuffer->Mutex, ProcessHandle, &NewBuffer->ClientMutex, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("NtDuplicateObject() failed: %lu\n", Status); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a memory section for the bitmap area, to share with the client. */ SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage; Status = NtCreateSection(&NewBuffer->hSection, SECTION_ALL_ACCESS, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a view for our needs. */ ViewSize = 0; NewBuffer->BitMap = NULL; Status = NtMapViewOfSection(NewBuffer->hSection, NtCurrentProcess(), (PVOID*)&NewBuffer->BitMap, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status); NtClose(NewBuffer->hSection); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a view for the client. We must keep a trace of it so that * we can unmap it when the client releases the screen buffer. */ ViewSize = 0; NewBuffer->ClientBitMap = NULL; Status = NtMapViewOfSection(NewBuffer->hSection, ProcessHandle, (PVOID*)&NewBuffer->ClientBitMap, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status); NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap); NtClose(NewBuffer->hSection); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0; NewBuffer->VirtualY = 0; NewBuffer->CursorBlinkOn = FALSE; NewBuffer->ForceCursorOff = TRUE; NewBuffer->CursorInfo.bVisible = FALSE; NewBuffer->CursorInfo.dwSize = 0; NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0; NewBuffer->Mode = 0; *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer; Status = STATUS_SUCCESS; Quit: return Status; }