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)
10 /* INCLUDES *******************************************************************/
17 /* PRIVATE FUNCTIONS **********************************************************/
20 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
22 IN HANDLE ProcessHandle
,
23 IN PTEXTMODE_BUFFER_INFO TextModeInfo
);
25 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
27 IN HANDLE ProcessHandle
,
28 IN PGRAPHICS_BUFFER_INFO GraphicsInfo
);
31 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
33 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
37 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
39 IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl
,
42 if (Buffer
== NULL
|| Console
== NULL
)
43 return STATUS_INVALID_PARAMETER
;
45 *Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, max(sizeof(CONSOLE_SCREEN_BUFFER
), Size
));
46 if (*Buffer
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
48 /* Initialize the header with the default type */
49 ConSrvInitObject(&(*Buffer
)->Header
, SCREEN_BUFFER
, Console
);
50 (*Buffer
)->Vtbl
= Vtbl
;
51 return STATUS_SUCCESS
;
55 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
)
57 if (Buffer
->Header
.Type
== TEXTMODE_BUFFER
)
59 TEXTMODE_BUFFER_Destroy(Buffer
);
61 else if (Buffer
->Header
.Type
== GRAPHICS_BUFFER
)
63 GRAPHICS_BUFFER_Destroy(Buffer
);
65 else if (Buffer
->Header
.Type
== SCREEN_BUFFER
)
67 /* Free the palette handle */
68 if (Buffer
->PaletteHandle
!= NULL
) DeleteObject(Buffer
->PaletteHandle
);
70 /* Free the screen buffer memory */
71 ConsoleFreeHeap(Buffer
);
77 // ConDrvCreateConsoleScreenBuffer
79 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
81 IN HANDLE ProcessHandle OPTIONAL
,
83 IN PVOID ScreenBufferInfo
)
85 NTSTATUS Status
= STATUS_SUCCESS
;
87 if ( Console
== NULL
|| Buffer
== NULL
||
88 (BufferType
!= CONSOLE_TEXTMODE_BUFFER
&& BufferType
!= CONSOLE_GRAPHICS_BUFFER
) )
90 return STATUS_INVALID_PARAMETER
;
93 /* Use the current process if ProcessHandle is NULL */
94 if (ProcessHandle
== NULL
)
95 ProcessHandle
= NtCurrentProcess();
97 if (BufferType
== CONSOLE_TEXTMODE_BUFFER
)
99 Status
= TEXTMODE_BUFFER_Initialize(Buffer
, Console
, ProcessHandle
,
100 (PTEXTMODE_BUFFER_INFO
)ScreenBufferInfo
);
102 else if (BufferType
== CONSOLE_GRAPHICS_BUFFER
)
104 Status
= GRAPHICS_BUFFER_Initialize(Buffer
, Console
, ProcessHandle
,
105 (PGRAPHICS_BUFFER_INFO
)ScreenBufferInfo
);
109 /* Never ever go there!! */
113 /* Insert the newly created screen buffer into the list, if succeeded */
114 if (NT_SUCCESS(Status
)) InsertHeadList(&Console
->BufferList
, &(*Buffer
)->ListEntry
);
120 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
);
123 ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
125 PCONSOLE Console
= Buffer
->Header
.Console
;
126 PCONSOLE_SCREEN_BUFFER NewBuffer
;
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
135 TermReleaseScreenBuffer(Console
, Buffer
);
137 RemoveEntryList(&Buffer
->ListEntry
);
138 if (Buffer
== Console
->ActiveBuffer
)
140 /* Delete active buffer; switch to most recently created */
141 if (!IsListEmpty(&Console
->BufferList
))
143 NewBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
,
144 CONSOLE_SCREEN_BUFFER
,
147 /* Tie console to new buffer and signal the change to the frontend */
148 ConioSetActiveScreenBuffer(NewBuffer
);
152 Console
->ActiveBuffer
= NULL
;
153 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
157 CONSOLE_SCREEN_BUFFER_Destroy(Buffer
);
161 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
163 PCONSOLE Console
= Buffer
->Header
.Console
;
164 Console
->ActiveBuffer
= Buffer
;
165 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
166 TermSetActiveScreenBuffer(Console
);
170 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
171 IN PCONSOLE_SCREEN_BUFFER Buffer
)
173 if (Console
== NULL
|| Buffer
== NULL
)
174 return STATUS_INVALID_PARAMETER
;
177 ASSERT(Console
== Buffer
->Header
.Console
);
179 if (Buffer
== Console
->ActiveBuffer
) return STATUS_SUCCESS
;
181 /* If old buffer has no handles, it's now unreferenced */
182 if (Console
->ActiveBuffer
->Header
.ReferenceCount
== 0)
184 ConDrvDeleteScreenBuffer(Console
->ActiveBuffer
);
187 /* Tie console to new buffer and signal the change to the frontend */
188 ConioSetActiveScreenBuffer(Buffer
);
190 return STATUS_SUCCESS
;
193 PCONSOLE_SCREEN_BUFFER
194 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console
)
196 return (Console
? Console
->ActiveBuffer
: NULL
);
199 /* PUBLIC DRIVER APIS *********************************************************/
202 ConDrvInvalidateBitMapRect(IN PCONSOLE Console
,
203 IN PCONSOLE_SCREEN_BUFFER Buffer
,
204 IN PSMALL_RECT Region
)
206 if (Console
== NULL
|| Buffer
== NULL
|| Region
== NULL
)
207 return STATUS_INVALID_PARAMETER
;
210 ASSERT(Console
== Buffer
->Header
.Console
);
212 /* If the output buffer is the current one, redraw the correct portion of the screen */
213 if (Buffer
== Console
->ActiveBuffer
) TermDrawRegion(Console
, Region
);
215 return STATUS_SUCCESS
;
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
)
228 * Parameters validation
230 if (Console
== NULL
|| Buffer
== NULL
)
231 return STATUS_INVALID_PARAMETER
;
233 if ( PaletteUsage
!= SYSPAL_STATIC
&&
234 PaletteUsage
!= SYSPAL_NOSTATIC
&&
235 PaletteUsage
!= SYSPAL_NOSTATIC256
)
237 return STATUS_INVALID_PARAMETER
;
241 ASSERT(Console
== Buffer
->Header
.Console
);
243 /* Change the palette */
244 Success
= TermSetPalette(Console
, PaletteHandle
, PaletteUsage
);
247 /* Free the old palette handle if there was already one set */
248 if ( Buffer
->PaletteHandle
!= NULL
&&
249 Buffer
->PaletteHandle
!= PaletteHandle
)
251 DeleteObject(Buffer
->PaletteHandle
);
254 /* Save the new palette in the screen buffer */
255 Buffer
->PaletteHandle
= PaletteHandle
;
256 Buffer
->PaletteUsage
= PaletteUsage
;
259 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
263 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
264 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
265 OUT PCONSOLE_CURSOR_INFO CursorInfo
)
267 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
268 return STATUS_INVALID_PARAMETER
;
271 ASSERT(Console
== Buffer
->Header
.Console
);
273 *CursorInfo
= Buffer
->CursorInfo
;
274 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
275 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
277 return STATUS_SUCCESS
;
281 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
282 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
283 IN PCONSOLE_CURSOR_INFO CursorInfo
)
286 BOOLEAN Visible
, Success
= TRUE
;
288 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
289 return STATUS_INVALID_PARAMETER
;
292 ASSERT(Console
== Buffer
->Header
.Console
);
294 Size
= min(max(CursorInfo
->dwSize
, 1), 100);
295 Visible
= CursorInfo
->bVisible
;
297 if ( (Size
!= Buffer
->CursorInfo
.dwSize
) ||
298 (Visible
&& !Buffer
->CursorInfo
.bVisible
) ||
299 (!Visible
&& Buffer
->CursorInfo
.bVisible
) )
301 Buffer
->CursorInfo
.dwSize
= Size
;
302 Buffer
->CursorInfo
.bVisible
= Visible
;
304 Success
= TermSetCursorInfo(Console
, (PCONSOLE_SCREEN_BUFFER
)Buffer
);
307 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
311 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
312 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
315 SHORT OldCursorX
, OldCursorY
;
317 if (Console
== NULL
|| Buffer
== NULL
|| Position
== NULL
)
318 return STATUS_INVALID_PARAMETER
;
321 ASSERT(Console
== Buffer
->Header
.Console
);
323 if ( Position
->X
< 0 || Position
->X
>= Buffer
->ScreenBufferSize
.X
||
324 Position
->Y
< 0 || Position
->Y
>= Buffer
->ScreenBufferSize
.Y
)
326 return STATUS_INVALID_PARAMETER
;
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
)) )
337 return STATUS_UNSUCCESSFUL
;
340 return STATUS_SUCCESS
;