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