2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/init.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
14 #include "include/conio.h"
15 #include "include/console.h"
21 /* GLOBALS ********************************************************************/
23 HINSTANCE ConSrvDllInstance
= NULL
;
26 HANDLE ConSrvHeap
= NULL
; // Our own heap.
28 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
29 // plus a little bit of Windows 7.
30 PCSR_API_ROUTINE ConsoleServerApiDispatchTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
36 SrvWriteConsoleOutput
,
37 SrvReadConsoleOutputString
,
38 SrvWriteConsoleOutputString
,
41 // SrvGetConsoleNumberOfFonts,
42 SrvGetConsoleNumberOfInputEvents
,
43 SrvGetConsoleScreenBufferInfo
,
44 SrvGetConsoleCursorInfo
,
45 // SrvGetConsoleMouseInfo,
46 // SrvGetConsoleFontInfo,
47 // SrvGetConsoleFontSize,
48 // SrvGetConsoleCurrentFont,
50 SrvSetConsoleActiveScreenBuffer
,
51 SrvFlushConsoleInputBuffer
,
52 SrvGetLargestConsoleWindowSize
,
53 SrvSetConsoleScreenBufferSize
,
54 SrvSetConsoleCursorPosition
,
55 SrvSetConsoleCursorInfo
,
56 SrvSetConsoleWindowInfo
,
57 SrvScrollConsoleScreenBuffer
,
58 SrvSetConsoleTextAttribute
,
64 // SrvGetHandleInformation,
65 // SrvSetHandleInformation,
67 SrvVerifyConsoleIoHandle
,
72 SrvCreateConsoleScreenBuffer
,
73 SrvInvalidateBitMapRect
,
74 // SrvVDMConsoleOperation,
75 // SrvSetConsoleCursor,
76 // SrvShowConsoleCursor,
77 SrvConsoleMenuControl
,
78 // SrvSetConsolePalette,
79 SrvSetConsoleDisplayMode
,
80 // SrvRegisterConsoleVDM,
81 SrvGetConsoleHardwareState
,
82 SrvSetConsoleHardwareState
,
83 SrvGetConsoleDisplayMode
,
86 SrvGetConsoleAliasesLength
,
87 SrvGetConsoleAliasExesLength
,
89 SrvGetConsoleAliasExes
,
90 SrvExpungeConsoleCommandHistory
,
91 SrvSetConsoleNumberOfCommands
,
92 SrvGetConsoleCommandHistoryLength
,
93 SrvGetConsoleCommandHistory
,
94 // SrvSetConsoleCommandHistoryMode,
97 // SrvSetConsoleKeyShortcuts,
98 SrvSetConsoleMenuClose
,
99 // SrvConsoleNotifyLastClose,
100 SrvGenerateConsoleCtrlEvent
,
101 // SrvGetConsoleKeyboardLayoutName,
103 // SrvGetConsoleCharType,
104 // SrvSetConsoleLocalEUDC,
105 // SrvSetConsoleCursorMode,
106 // SrvGetConsoleCursorMode,
107 // SrvRegisterConsoleOS2,
108 // SrvSetConsoleOS2OemFormat,
109 // SrvGetConsoleNlsMode,
110 // SrvSetConsoleNlsMode,
111 // SrvRegisterConsoleIME,
112 // SrvUnregisterConsoleIME,
113 // SrvGetConsoleLangId,
115 SrvGetConsoleSelectionInfo
,
116 SrvGetConsoleProcessList
,
117 SrvGetConsoleHistory
,
118 SrvSetConsoleHistory
,
121 BOOLEAN ConsoleServerApiServerValidTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
123 FALSE
, // SrvOpenConsole,
124 FALSE
, // SrvGetConsoleInput,
125 FALSE
, // SrvWriteConsoleInput,
126 FALSE
, // SrvReadConsoleOutput,
127 FALSE
, // SrvWriteConsoleOutput,
128 FALSE
, // SrvReadConsoleOutputString,
129 FALSE
, // SrvWriteConsoleOutputString,
130 FALSE
, // SrvFillConsoleOutput,
131 FALSE
, // SrvGetConsoleMode,
132 // FALSE, // SrvGetConsoleNumberOfFonts,
133 FALSE
, // SrvGetConsoleNumberOfInputEvents,
134 FALSE
, // SrvGetConsoleScreenBufferInfo,
135 FALSE
, // SrvGetConsoleCursorInfo,
136 // FALSE, // SrvGetConsoleMouseInfo,
137 // FALSE, // SrvGetConsoleFontInfo,
138 // FALSE, // SrvGetConsoleFontSize,
139 // FALSE, // SrvGetConsoleCurrentFont,
140 FALSE
, // SrvSetConsoleMode,
141 FALSE
, // SrvSetConsoleActiveScreenBuffer,
142 FALSE
, // SrvFlushConsoleInputBuffer,
143 FALSE
, // SrvGetLargestConsoleWindowSize,
144 FALSE
, // SrvSetConsoleScreenBufferSize,
145 FALSE
, // SrvSetConsoleCursorPosition,
146 FALSE
, // SrvSetConsoleCursorInfo,
147 FALSE
, // SrvSetConsoleWindowInfo,
148 FALSE
, // SrvScrollConsoleScreenBuffer,
149 FALSE
, // SrvSetConsoleTextAttribute,
150 // FALSE, // SrvSetConsoleFont,
151 FALSE
, // SrvSetConsoleIcon,
152 FALSE
, // SrvReadConsole,
153 FALSE
, // SrvWriteConsole,
154 FALSE
, // SrvDuplicateHandle,
155 // FALSE, // SrvGetHandleInformation,
156 // FALSE, // SrvSetHandleInformation,
157 FALSE
, // SrvCloseHandle,
158 FALSE
, // SrvVerifyConsoleIoHandle,
159 FALSE
, // SrvAllocConsole,
160 FALSE
, // SrvFreeConsole,
161 FALSE
, // SrvGetConsoleTitle,
162 FALSE
, // SrvSetConsoleTitle,
163 FALSE
, // SrvCreateConsoleScreenBuffer,
164 FALSE
, // SrvInvalidateBitMapRect,
165 // FALSE, // SrvVDMConsoleOperation,
166 // FALSE, // SrvSetConsoleCursor,
167 // FALSE, // SrvShowConsoleCursor,
168 FALSE
, // SrvConsoleMenuControl,
169 // FALSE, // SrvSetConsolePalette,
170 FALSE
, // SrvSetConsoleDisplayMode,
171 // FALSE, // SrvRegisterConsoleVDM,
172 FALSE
, // SrvGetConsoleHardwareState,
173 FALSE
, // SrvSetConsoleHardwareState,
174 TRUE
, // SrvGetConsoleDisplayMode,
175 FALSE
, // SrvAddConsoleAlias,
176 FALSE
, // SrvGetConsoleAlias,
177 FALSE
, // SrvGetConsoleAliasesLength,
178 FALSE
, // SrvGetConsoleAliasExesLength,
179 FALSE
, // SrvGetConsoleAliases,
180 FALSE
, // SrvGetConsoleAliasExes,
181 FALSE
, // SrvExpungeConsoleCommandHistory,
182 FALSE
, // SrvSetConsoleNumberOfCommands,
183 FALSE
, // SrvGetConsoleCommandHistoryLength,
184 FALSE
, // SrvGetConsoleCommandHistory,
185 // FALSE, // SrvSetConsoleCommandHistoryMode,
186 FALSE
, // SrvGetConsoleCP,
187 FALSE
, // SrvSetConsoleCP,
188 // FALSE, // SrvSetConsoleKeyShortcuts,
189 FALSE
, // SrvSetConsoleMenuClose,
190 // FALSE, // SrvConsoleNotifyLastClose,
191 FALSE
, // SrvGenerateConsoleCtrlEvent,
192 // FALSE, // SrvGetConsoleKeyboardLayoutName,
193 FALSE
, // SrvGetConsoleWindow,
194 // FALSE, // SrvGetConsoleCharType,
195 // FALSE, // SrvSetConsoleLocalEUDC,
196 // FALSE, // SrvSetConsoleCursorMode,
197 // FALSE, // SrvGetConsoleCursorMode,
198 // FALSE, // SrvRegisterConsoleOS2,
199 // FALSE, // SrvSetConsoleOS2OemFormat,
200 // FALSE, // SrvGetConsoleNlsMode,
201 // FALSE, // SrvSetConsoleNlsMode,
202 // FALSE, // SrvRegisterConsoleIME,
203 // FALSE, // SrvUnregisterConsoleIME,
204 // FALSE, // SrvGetConsoleLangId,
205 FALSE
, // SrvAttachConsole,
206 FALSE
, // SrvGetConsoleSelectionInfo,
207 FALSE
, // SrvGetConsoleProcessList,
208 FALSE
, // SrvGetConsoleHistory,
209 FALSE
, // SrvSetConsoleHistory
212 PCHAR ConsoleServerApiNameTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
218 "WriteConsoleOutput",
219 "ReadConsoleOutputString",
220 "WriteConsoleOutputString",
223 // "GetConsoleNumberOfFonts",
224 "GetConsoleNumberOfInputEvents",
225 "GetConsoleScreenBufferInfo",
226 "GetConsoleCursorInfo",
227 // "GetConsoleMouseInfo",
228 // "GetConsoleFontInfo",
229 // "GetConsoleFontSize",
230 // "GetConsoleCurrentFont",
232 "SetConsoleActiveScreenBuffer",
233 "FlushConsoleInputBuffer",
234 "GetLargestConsoleWindowSize",
235 "SetConsoleScreenBufferSize",
236 "SetConsoleCursorPosition",
237 "SetConsoleCursorInfo",
238 "SetConsoleWindowInfo",
239 "ScrollConsoleScreenBuffer",
240 "SetConsoleTextAttribute",
246 // "GetHandleInformation",
247 // "SetHandleInformation",
249 "VerifyConsoleIoHandle",
254 "CreateConsoleScreenBuffer",
255 "InvalidateBitMapRect",
256 // "VDMConsoleOperation",
257 // "SetConsoleCursor",
258 // "ShowConsoleCursor",
259 "ConsoleMenuControl",
260 // "SetConsolePalette",
261 "SetConsoleDisplayMode",
262 // "RegisterConsoleVDM",
263 "GetConsoleHardwareState",
264 "SetConsoleHardwareState",
265 "GetConsoleDisplayMode",
268 "GetConsoleAliasesLength",
269 "GetConsoleAliasExesLength",
271 "GetConsoleAliasExes",
272 "ExpungeConsoleCommandHistory",
273 "SetConsoleNumberOfCommands",
274 "GetConsoleCommandHistoryLength",
275 "GetConsoleCommandHistory",
276 // "SetConsoleCommandHistoryMode",
279 // "SetConsoleKeyShortcuts",
280 "SetConsoleMenuClose",
281 // "ConsoleNotifyLastClose",
282 "GenerateConsoleCtrlEvent",
283 // "GetConsoleKeyboardLayoutName",
285 // "GetConsoleCharType",
286 // "SetConsoleLocalEUDC",
287 // "SetConsoleCursorMode",
288 // "GetConsoleCursorMode",
289 // "RegisterConsoleOS2",
290 // "SetConsoleOS2OemFormat",
291 // "GetConsoleNlsMode",
292 // "SetConsoleNlsMode",
293 // "RegisterConsoleIME",
294 // "UnregisterConsoleIME",
295 // "GetConsoleLangId",
297 "GetConsoleSelectionInfo",
298 "GetConsoleProcessList",
304 /* FUNCTIONS ******************************************************************/
308 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
309 IN PCONSOLE_PROCESS_DATA TargetProcessData
);
313 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
314 PCSR_PROCESS TargetProcess
)
316 /**************************************************************************
317 * This function is called whenever a new process (GUI or CUI) is created.
319 * Copy the parent's handles table here if both the parent and the child
320 * processes are CUI. If we must actually create our proper console (and
321 * thus do not inherit from the console handles of the parent's), then we
322 * will clean this table in the next ConSrvConnect call. Why we are doing
323 * this? It's because here, we still don't know whether or not we must create
324 * a new console instead of inherit it from the parent, and, because in
325 * ConSrvConnect we don't have any reference to the parent process anymore.
326 **************************************************************************/
328 NTSTATUS Status
= STATUS_SUCCESS
;
329 PCONSOLE_PROCESS_DATA
/* SourceProcessData, */ TargetProcessData
;
331 /* An empty target process is invalid */
332 if (!TargetProcess
) return STATUS_INVALID_PARAMETER
;
334 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
336 /* Initialize the new (target) process */
337 RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
338 TargetProcessData
->Process
= TargetProcess
;
339 TargetProcessData
->ConsoleEvent
= NULL
;
340 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
341 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
344 * The handles table gets initialized either when inheriting from
345 * another console process, or when creating a new console.
347 TargetProcessData
->HandleTableSize
= 0;
348 TargetProcessData
->HandleTable
= NULL
;
350 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
352 /* Do nothing if the source process is NULL */
353 if (!SourceProcess
) return STATUS_SUCCESS
;
355 // SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
358 * If the child process is a console application and the parent process is
359 * either a console application or just has a valid console (with a valid
360 * handles table: this can happen if it is a GUI application having called
361 * AllocConsole), then try to inherit handles from the parent process.
363 if (TargetProcessData
->ConsoleApp
/* && SourceProcessData->ConsoleApp */)
365 PCONSOLE_PROCESS_DATA SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
367 /* Validate and lock the parent's console */
368 if (ConSrvValidateConsole(SourceProcessData
->Console
, CONSOLE_RUNNING
, TRUE
))
370 /* Inherit the parent's handles table */
371 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
372 if (NT_SUCCESS(Status
))
374 /* Temporary save the parent's console too */
375 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
378 /* Unlock the parent's console */
379 LeaveCriticalSection(&SourceProcessData
->Console
->Lock
);
388 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
389 IN OUT PVOID ConnectionInfo
,
390 IN OUT PULONG ConnectionInfoLength
)
392 /**************************************************************************
393 * This function is called whenever a CUI new process is created.
394 **************************************************************************/
396 NTSTATUS Status
= STATUS_SUCCESS
;
397 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
398 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
400 if ( ConnectionInfo
== NULL
||
401 ConnectionInfoLength
== NULL
||
402 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
404 DPRINT1("CONSRV: Connection failed\n");
405 return STATUS_UNSUCCESSFUL
;
408 /* If we don't need a console, then get out of here */
409 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
411 return STATUS_SUCCESS
;
414 /* If we don't have a console, then create a new one... */
415 if (!ConnectInfo
->Console
||
416 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
418 DPRINT("ConSrvConnect - Allocate a new console\n");
421 * We are about to create a new console. However when ConSrvNewProcess
422 * was called, we didn't know that we wanted to create a new console and
423 * therefore, we by default inherited the handles table from our parent
424 * process. It's only now that we notice that in fact we do not need
425 * them, because we've created a new console and thus we must use it.
427 * ConSrvAllocateConsole will free our old handles table
428 * and recreate a new valid one.
431 /* Initialize a new Console owned by the Console Leader Process */
432 Status
= ConSrvAllocateConsole(ProcessData
,
433 &ConnectInfo
->InputHandle
,
434 &ConnectInfo
->OutputHandle
,
435 &ConnectInfo
->ErrorHandle
,
436 &ConnectInfo
->ConsoleStartInfo
);
437 if (!NT_SUCCESS(Status
))
439 DPRINT1("Console allocation failed\n");
443 else /* We inherit it from the parent */
445 DPRINT("ConSrvConnect - Reuse current (parent's) console\n");
447 /* Reuse our current console */
448 Status
= ConSrvInheritConsole(ProcessData
,
449 ConnectInfo
->Console
,
451 NULL
, // &ConnectInfo->InputHandle,
452 NULL
, // &ConnectInfo->OutputHandle,
453 NULL
); // &ConnectInfo->ErrorHandle);
454 if (!NT_SUCCESS(Status
))
456 DPRINT1("Console inheritance failed\n");
461 /* Return it to the caller */
462 ConnectInfo
->Console
= ProcessData
->Console
;
464 /* Input Wait Handle */
465 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
467 /* Set the Property Dialog Handler */
468 ProcessData
->PropDispatcher
= ConnectInfo
->PropDispatcher
;
470 /* Set the Ctrl Dispatcher */
471 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
473 return STATUS_SUCCESS
;
478 ConSrvDisconnect(PCSR_PROCESS Process
)
480 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
482 /**************************************************************************
483 * This function is called whenever a new process (GUI or CUI) is destroyed.
484 **************************************************************************/
486 if ( ProcessData
->Console
!= NULL
||
487 ProcessData
->HandleTable
!= NULL
)
489 DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
490 ConSrvRemoveConsole(ProcessData
);
493 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
496 CSR_SERVER_DLL_INIT(ConServerDllInitialization
)
498 /* Initialize the memory */
499 ConSrvHeap
= RtlGetProcessHeap();
501 // We can use our own heap instead of the CSR heap to investigate heap corruptions :)
502 ConSrvHeap = RtlCreateHeap(HEAP_GROWABLE |
503 HEAP_PROTECTION_ENABLED |
504 HEAP_FREE_CHECKING_ENABLED |
505 HEAP_TAIL_CHECKING_ENABLED |
506 HEAP_VALIDATE_ALL_ENABLED,
507 NULL, 0, 0, NULL, NULL);
508 if (!ConSrvHeap) return STATUS_NO_MEMORY;
511 ConSrvInitConsoleSupport();
513 /* Setup the DLL Object */
514 LoadedServerDll
->ApiBase
= CONSRV_FIRST_API_NUMBER
;
515 LoadedServerDll
->HighestApiSupported
= ConsolepMaxApiNumber
;
516 LoadedServerDll
->DispatchTable
= ConsoleServerApiDispatchTable
;
517 LoadedServerDll
->ValidTable
= ConsoleServerApiServerValidTable
;
518 LoadedServerDll
->NameTable
= ConsoleServerApiNameTable
;
519 LoadedServerDll
->SizeOfProcessData
= sizeof(CONSOLE_PROCESS_DATA
);
520 LoadedServerDll
->ConnectCallback
= ConSrvConnect
;
521 LoadedServerDll
->DisconnectCallback
= ConSrvDisconnect
;
522 LoadedServerDll
->NewProcessCallback
= ConSrvNewProcess
;
523 // LoadedServerDll->HardErrorCallback = ConSrvHardError;
524 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
526 ConSrvDllInstance
= LoadedServerDll
->ServerHandle
;
529 return STATUS_SUCCESS
;
534 DllMain(IN HINSTANCE hInstanceDll
,
536 IN LPVOID lpReserved
)
538 UNREFERENCED_PARAMETER(hInstanceDll
);
539 UNREFERENCED_PARAMETER(dwReason
);
540 UNREFERENCED_PARAMETER(lpReserved
);