1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Console Driver DLL 4 * FILE: win32ss/user/winsrv/consrv/condrv/conoutput.c 5 * PURPOSE: General Console Output Functions 6 * PROGRAMMERS: Jeffrey Morlan 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 /* INCLUDES *******************************************************************/ 11 12 #include <consrv.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* PRIVATE FUNCTIONS **********************************************************/ 18 19 NTSTATUS 20 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, 21 IN PCONSOLE Console, 22 IN HANDLE ProcessHandle, 23 IN PTEXTMODE_BUFFER_INFO TextModeInfo); 24 NTSTATUS 25 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, 26 IN PCONSOLE Console, 27 IN HANDLE ProcessHandle, 28 IN PGRAPHICS_BUFFER_INFO GraphicsInfo); 29 30 VOID 31 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer); 32 VOID 33 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer); 34 35 36 NTSTATUS 37 CONSOLE_SCREEN_BUFFER_Initialize( 38 OUT PCONSOLE_SCREEN_BUFFER* Buffer, 39 IN PCONSOLE Console, 40 IN CONSOLE_IO_OBJECT_TYPE Type, 41 IN SIZE_T Size) 42 { 43 if (Buffer == NULL || Console == NULL) 44 return STATUS_INVALID_PARAMETER; 45 46 *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size)); 47 if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; 48 49 /* Initialize the header with the default type */ 50 ConSrvInitObject(&(*Buffer)->Header, Type /* SCREEN_BUFFER */, Console); 51 return STATUS_SUCCESS; 52 } 53 54 VOID 55 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer) 56 { 57 switch (Buffer->Header.Type) 58 { 59 case TEXTMODE_BUFFER: 60 TEXTMODE_BUFFER_Destroy(Buffer); 61 break; 62 63 case GRAPHICS_BUFFER: 64 GRAPHICS_BUFFER_Destroy(Buffer); 65 break; 66 67 case SCREEN_BUFFER: 68 { 69 /* Free the palette handle */ 70 if (Buffer->PaletteHandle != NULL) 71 DeleteObject(Buffer->PaletteHandle); 72 73 /* Free the screen buffer memory */ 74 ConsoleFreeHeap(Buffer); 75 break; 76 } 77 78 default: 79 break; 80 } 81 } 82 83 // ConDrvCreateConsoleScreenBuffer 84 NTSTATUS 85 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer, 86 IN PCONSOLE Console, 87 IN HANDLE ProcessHandle OPTIONAL, 88 IN ULONG BufferType, 89 IN PVOID ScreenBufferInfo) 90 { 91 NTSTATUS Status = STATUS_UNSUCCESSFUL; 92 93 if ( Console == NULL || Buffer == NULL || 94 (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) ) 95 { 96 return STATUS_INVALID_PARAMETER; 97 } 98 99 /* Use the current process if ProcessHandle is NULL */ 100 if (ProcessHandle == NULL) 101 ProcessHandle = NtCurrentProcess(); 102 103 switch (BufferType) 104 { 105 case CONSOLE_TEXTMODE_BUFFER: 106 Status = TEXTMODE_BUFFER_Initialize(Buffer, Console, ProcessHandle, 107 (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo); 108 break; 109 110 case CONSOLE_GRAPHICS_BUFFER: 111 Status = GRAPHICS_BUFFER_Initialize(Buffer, Console, ProcessHandle, 112 (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo); 113 break; 114 115 default: 116 /* Never ever go there!! */ 117 ASSERT(FALSE); 118 } 119 120 /* Insert the newly created screen buffer into the list, if succeeded */ 121 if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry); 122 123 return Status; 124 } 125 126 static VOID 127 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); 128 129 VOID NTAPI 130 ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) 131 { 132 PCONSOLE Console = Buffer->Header.Console; 133 PCONSOLE_SCREEN_BUFFER NewBuffer; 134 135 /* 136 * We should notify temporarily the frontend because we are susceptible 137 * to delete the screen buffer it is using (which may be different from 138 * the active screen buffer in some cases), and because, if it actually 139 * uses the active screen buffer, we are going to nullify its pointer to 140 * change it. 141 */ 142 TermReleaseScreenBuffer(Console, Buffer); 143 144 RemoveEntryList(&Buffer->ListEntry); 145 if (Buffer == Console->ActiveBuffer) 146 { 147 /* Delete active buffer; switch to most recently created */ 148 if (!IsListEmpty(&Console->BufferList)) 149 { 150 NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink, 151 CONSOLE_SCREEN_BUFFER, 152 ListEntry); 153 154 /* Tie console to new buffer and signal the change to the frontend */ 155 ConioSetActiveScreenBuffer(NewBuffer); 156 } 157 else 158 { 159 Console->ActiveBuffer = NULL; 160 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL); 161 } 162 } 163 164 CONSOLE_SCREEN_BUFFER_Destroy(Buffer); 165 } 166 167 static VOID 168 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) 169 { 170 PCONSOLE Console = Buffer->Header.Console; 171 Console->ActiveBuffer = Buffer; 172 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer); 173 TermSetActiveScreenBuffer(Console); 174 } 175 176 NTSTATUS NTAPI 177 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console, 178 IN PCONSOLE_SCREEN_BUFFER Buffer) 179 { 180 if (Console == NULL || Buffer == NULL) 181 return STATUS_INVALID_PARAMETER; 182 183 /* Validity check */ 184 ASSERT(Console == Buffer->Header.Console); 185 186 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS; 187 188 /* If old buffer has no handles, it's now unreferenced */ 189 if (Console->ActiveBuffer->Header.ReferenceCount == 0) 190 { 191 ConDrvDeleteScreenBuffer(Console->ActiveBuffer); 192 } 193 194 /* Tie console to new buffer and signal the change to the frontend */ 195 ConioSetActiveScreenBuffer(Buffer); 196 197 return STATUS_SUCCESS; 198 } 199 200 PCONSOLE_SCREEN_BUFFER 201 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console) 202 { 203 return (Console ? Console->ActiveBuffer : NULL); 204 } 205 206 /* PUBLIC DRIVER APIS *********************************************************/ 207 208 NTSTATUS NTAPI 209 ConDrvInvalidateBitMapRect(IN PCONSOLE Console, 210 IN PCONSOLE_SCREEN_BUFFER Buffer, 211 IN PSMALL_RECT Region) 212 { 213 if (Console == NULL || Buffer == NULL || Region == NULL) 214 return STATUS_INVALID_PARAMETER; 215 216 /* Validity check */ 217 ASSERT(Console == Buffer->Header.Console); 218 219 /* If the output buffer is the current one, redraw the correct portion of the screen */ 220 if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region); 221 222 return STATUS_SUCCESS; 223 } 224 225 NTSTATUS NTAPI 226 ConDrvSetConsolePalette(IN PCONSOLE Console, 227 // IN PGRAPHICS_SCREEN_BUFFER Buffer, 228 IN PCONSOLE_SCREEN_BUFFER Buffer, 229 IN HPALETTE PaletteHandle, 230 IN UINT PaletteUsage) 231 { 232 BOOL Success; 233 234 /* 235 * Parameters validation 236 */ 237 if (Console == NULL || Buffer == NULL) 238 return STATUS_INVALID_PARAMETER; 239 240 if ( PaletteUsage != SYSPAL_STATIC && 241 PaletteUsage != SYSPAL_NOSTATIC && 242 PaletteUsage != SYSPAL_NOSTATIC256 ) 243 { 244 return STATUS_INVALID_PARAMETER; 245 } 246 247 /* Validity check */ 248 ASSERT(Console == Buffer->Header.Console); 249 250 /* Change the palette */ 251 Success = TermSetPalette(Console, PaletteHandle, PaletteUsage); 252 if (Success) 253 { 254 /* Free the old palette handle if there was already one set */ 255 if ( Buffer->PaletteHandle != NULL && 256 Buffer->PaletteHandle != PaletteHandle ) 257 { 258 DeleteObject(Buffer->PaletteHandle); 259 } 260 261 /* Save the new palette in the screen buffer */ 262 Buffer->PaletteHandle = PaletteHandle; 263 Buffer->PaletteUsage = PaletteUsage; 264 } 265 266 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); 267 } 268 269 NTSTATUS NTAPI 270 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console, 271 IN PTEXTMODE_SCREEN_BUFFER Buffer, 272 OUT PCONSOLE_CURSOR_INFO CursorInfo) 273 { 274 if (Console == NULL || Buffer == NULL || CursorInfo == NULL) 275 return STATUS_INVALID_PARAMETER; 276 277 /* Validity check */ 278 ASSERT(Console == Buffer->Header.Console); 279 280 *CursorInfo = Buffer->CursorInfo; 281 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible; 282 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize; 283 284 return STATUS_SUCCESS; 285 } 286 287 NTSTATUS NTAPI 288 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console, 289 IN PTEXTMODE_SCREEN_BUFFER Buffer, 290 IN PCONSOLE_CURSOR_INFO CursorInfo) 291 { 292 ULONG Size; 293 BOOLEAN Visible, Success = TRUE; 294 295 if (Console == NULL || Buffer == NULL || CursorInfo == NULL) 296 return STATUS_INVALID_PARAMETER; 297 298 /* Validity check */ 299 ASSERT(Console == Buffer->Header.Console); 300 301 Size = min(max(CursorInfo->dwSize, 1), 100); 302 Visible = CursorInfo->bVisible; 303 304 if ( (Size != Buffer->CursorInfo.dwSize) || 305 (Visible && !Buffer->CursorInfo.bVisible) || 306 (!Visible && Buffer->CursorInfo.bVisible) ) 307 { 308 Buffer->CursorInfo.dwSize = Size; 309 Buffer->CursorInfo.bVisible = Visible; 310 311 Success = TermSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer); 312 } 313 314 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); 315 } 316 317 NTSTATUS NTAPI 318 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console, 319 IN PTEXTMODE_SCREEN_BUFFER Buffer, 320 IN PCOORD Position) 321 { 322 SHORT OldCursorX, OldCursorY; 323 324 if (Console == NULL || Buffer == NULL || Position == NULL) 325 return STATUS_INVALID_PARAMETER; 326 327 /* Validity check */ 328 ASSERT(Console == Buffer->Header.Console); 329 330 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X || 331 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y ) 332 { 333 return STATUS_INVALID_PARAMETER; 334 } 335 336 OldCursorX = Buffer->CursorPosition.X; 337 OldCursorY = Buffer->CursorPosition.Y; 338 Buffer->CursorPosition = *Position; 339 340 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) && 341 (!TermSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) ) 342 { 343 return STATUS_UNSUCCESSFUL; 344 } 345 346 return STATUS_SUCCESS; 347 } 348 349 /* EOF */ 350