2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/init.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
19 /* GLOBALS ********************************************************************/
21 HINSTANCE ConSrvDllInstance
= NULL
;
24 HANDLE ConSrvHeap
= NULL
; // Our own heap.
26 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
27 PCSR_API_ROUTINE ConsoleServerApiDispatchTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
33 SrvWriteConsoleOutput
,
34 SrvReadConsoleOutputString
,
35 SrvWriteConsoleOutputString
,
38 SrvGetConsoleNumberOfFonts
,
39 SrvGetConsoleNumberOfInputEvents
,
40 SrvGetConsoleScreenBufferInfo
,
41 SrvGetConsoleCursorInfo
,
42 SrvGetConsoleMouseInfo
,
43 SrvGetConsoleFontInfo
,
44 SrvGetConsoleFontSize
,
45 SrvGetConsoleCurrentFont
,
47 SrvSetConsoleActiveScreenBuffer
,
48 SrvFlushConsoleInputBuffer
,
49 SrvGetLargestConsoleWindowSize
,
50 SrvSetConsoleScreenBufferSize
,
51 SrvSetConsoleCursorPosition
,
52 SrvSetConsoleCursorInfo
,
53 SrvSetConsoleWindowInfo
,
54 SrvScrollConsoleScreenBuffer
,
55 SrvSetConsoleTextAttribute
,
61 SrvGetHandleInformation
,
62 SrvSetHandleInformation
,
64 SrvVerifyConsoleIoHandle
,
65 SrvAllocConsole
, // Not present in Win7
66 SrvFreeConsole
, // Not present in Win7
69 SrvCreateConsoleScreenBuffer
,
70 SrvInvalidateBitMapRect
,
71 SrvVDMConsoleOperation
,
74 SrvConsoleMenuControl
,
76 SrvSetConsoleDisplayMode
,
77 SrvRegisterConsoleVDM
,
78 SrvGetConsoleHardwareState
,
79 SrvSetConsoleHardwareState
,
80 SrvGetConsoleDisplayMode
,
83 SrvGetConsoleAliasesLength
,
84 SrvGetConsoleAliasExesLength
,
86 SrvGetConsoleAliasExes
,
87 SrvExpungeConsoleCommandHistory
,
88 SrvSetConsoleNumberOfCommands
,
89 SrvGetConsoleCommandHistoryLength
,
90 SrvGetConsoleCommandHistory
,
91 SrvSetConsoleCommandHistoryMode
, // Not present in Vista+
94 SrvSetConsoleKeyShortcuts
,
95 SrvSetConsoleMenuClose
,
96 SrvConsoleNotifyLastClose
,
97 SrvGenerateConsoleCtrlEvent
,
98 SrvGetConsoleKeyboardLayoutName
,
100 SrvGetConsoleCharType
,
101 SrvSetConsoleLocalEUDC
,
102 SrvSetConsoleCursorMode
,
103 SrvGetConsoleCursorMode
,
104 SrvRegisterConsoleOS2
,
105 SrvSetConsoleOS2OemFormat
,
106 SrvGetConsoleNlsMode
,
107 SrvSetConsoleNlsMode
,
108 SrvRegisterConsoleIME
, // Not present in Win7
109 SrvUnregisterConsoleIME
, // Not present in Win7
110 // SrvQueryConsoleIME, // Added only in Vista and Win2k8, not present in Win7
112 SrvAttachConsole
, // Not present in Win7
113 SrvGetConsoleSelectionInfo
,
114 SrvGetConsoleProcessList
,
116 SrvGetConsoleHistory
, // Added in Vista+
117 SrvSetConsoleHistory
, // Added in Vista+
118 // SrvSetConsoleCurrentFont, // Added in Vista+
119 // SrvSetScreenBufferInfo, // Added in Vista+
120 // SrvConsoleClientConnect, // Added in Win7
123 BOOLEAN ConsoleServerApiServerValidTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
125 FALSE
, // SrvOpenConsole,
126 FALSE
, // SrvGetConsoleInput,
127 FALSE
, // SrvWriteConsoleInput,
128 FALSE
, // SrvReadConsoleOutput,
129 FALSE
, // SrvWriteConsoleOutput,
130 FALSE
, // SrvReadConsoleOutputString,
131 FALSE
, // SrvWriteConsoleOutputString,
132 FALSE
, // SrvFillConsoleOutput,
133 FALSE
, // SrvGetConsoleMode,
134 FALSE
, // SrvGetConsoleNumberOfFonts,
135 FALSE
, // SrvGetConsoleNumberOfInputEvents,
136 FALSE
, // SrvGetConsoleScreenBufferInfo,
137 FALSE
, // SrvGetConsoleCursorInfo,
138 FALSE
, // SrvGetConsoleMouseInfo,
139 FALSE
, // SrvGetConsoleFontInfo,
140 FALSE
, // SrvGetConsoleFontSize,
141 FALSE
, // SrvGetConsoleCurrentFont,
142 FALSE
, // SrvSetConsoleMode,
143 FALSE
, // SrvSetConsoleActiveScreenBuffer,
144 FALSE
, // SrvFlushConsoleInputBuffer,
145 FALSE
, // SrvGetLargestConsoleWindowSize,
146 FALSE
, // SrvSetConsoleScreenBufferSize,
147 FALSE
, // SrvSetConsoleCursorPosition,
148 FALSE
, // SrvSetConsoleCursorInfo,
149 FALSE
, // SrvSetConsoleWindowInfo,
150 FALSE
, // SrvScrollConsoleScreenBuffer,
151 FALSE
, // SrvSetConsoleTextAttribute,
152 FALSE
, // SrvSetConsoleFont,
153 FALSE
, // SrvSetConsoleIcon,
154 FALSE
, // SrvReadConsole,
155 FALSE
, // SrvWriteConsole,
156 FALSE
, // SrvDuplicateHandle,
157 FALSE
, // SrvGetHandleInformation,
158 FALSE
, // SrvSetHandleInformation,
159 FALSE
, // SrvCloseHandle,
160 FALSE
, // SrvVerifyConsoleIoHandle,
161 FALSE
, // SrvAllocConsole,
162 FALSE
, // SrvFreeConsole,
163 FALSE
, // SrvGetConsoleTitle,
164 FALSE
, // SrvSetConsoleTitle,
165 FALSE
, // SrvCreateConsoleScreenBuffer,
166 FALSE
, // SrvInvalidateBitMapRect,
167 FALSE
, // SrvVDMConsoleOperation,
168 FALSE
, // SrvSetConsoleCursor,
169 FALSE
, // SrvShowConsoleCursor,
170 FALSE
, // SrvConsoleMenuControl,
171 FALSE
, // SrvSetConsolePalette,
172 FALSE
, // SrvSetConsoleDisplayMode,
173 FALSE
, // SrvRegisterConsoleVDM,
174 FALSE
, // SrvGetConsoleHardwareState,
175 FALSE
, // SrvSetConsoleHardwareState,
176 TRUE
, // SrvGetConsoleDisplayMode,
177 FALSE
, // SrvAddConsoleAlias,
178 FALSE
, // SrvGetConsoleAlias,
179 FALSE
, // SrvGetConsoleAliasesLength,
180 FALSE
, // SrvGetConsoleAliasExesLength,
181 FALSE
, // SrvGetConsoleAliases,
182 FALSE
, // SrvGetConsoleAliasExes,
183 FALSE
, // SrvExpungeConsoleCommandHistory,
184 FALSE
, // SrvSetConsoleNumberOfCommands,
185 FALSE
, // SrvGetConsoleCommandHistoryLength,
186 FALSE
, // SrvGetConsoleCommandHistory,
187 FALSE
, // SrvSetConsoleCommandHistoryMode,
188 FALSE
, // SrvGetConsoleCP,
189 FALSE
, // SrvSetConsoleCP,
190 FALSE
, // SrvSetConsoleKeyShortcuts,
191 FALSE
, // SrvSetConsoleMenuClose,
192 FALSE
, // SrvConsoleNotifyLastClose,
193 FALSE
, // SrvGenerateConsoleCtrlEvent,
194 FALSE
, // SrvGetConsoleKeyboardLayoutName,
195 FALSE
, // SrvGetConsoleWindow,
196 FALSE
, // SrvGetConsoleCharType,
197 FALSE
, // SrvSetConsoleLocalEUDC,
198 FALSE
, // SrvSetConsoleCursorMode,
199 FALSE
, // SrvGetConsoleCursorMode,
200 FALSE
, // SrvRegisterConsoleOS2,
201 FALSE
, // SrvSetConsoleOS2OemFormat,
202 FALSE
, // SrvGetConsoleNlsMode,
203 FALSE
, // SrvSetConsoleNlsMode,
204 FALSE
, // SrvRegisterConsoleIME,
205 FALSE
, // SrvUnregisterConsoleIME,
206 // FALSE, // SrvQueryConsoleIME,
207 FALSE
, // SrvGetConsoleLangId,
208 FALSE
, // SrvAttachConsole,
209 FALSE
, // SrvGetConsoleSelectionInfo,
210 FALSE
, // SrvGetConsoleProcessList,
212 FALSE
, // SrvGetConsoleHistory,
213 FALSE
, // SrvSetConsoleHistory
214 // FALSE, // SrvSetConsoleCurrentFont,
215 // FALSE, // SrvSetScreenBufferInfo,
216 // FALSE, // SrvConsoleClientConnect,
220 * On Windows Server 2003, CSR Servers contain
221 * the API Names Table only in Debug Builds.
224 PCHAR ConsoleServerApiNameTable
[ConsolepMaxApiNumber
- CONSRV_FIRST_API_NUMBER
] =
230 "WriteConsoleOutput",
231 "ReadConsoleOutputString",
232 "WriteConsoleOutputString",
235 "GetConsoleNumberOfFonts",
236 "GetConsoleNumberOfInputEvents",
237 "GetConsoleScreenBufferInfo",
238 "GetConsoleCursorInfo",
239 "GetConsoleMouseInfo",
240 "GetConsoleFontInfo",
241 "GetConsoleFontSize",
242 "GetConsoleCurrentFont",
244 "SetConsoleActiveScreenBuffer",
245 "FlushConsoleInputBuffer",
246 "GetLargestConsoleWindowSize",
247 "SetConsoleScreenBufferSize",
248 "SetConsoleCursorPosition",
249 "SetConsoleCursorInfo",
250 "SetConsoleWindowInfo",
251 "ScrollConsoleScreenBuffer",
252 "SetConsoleTextAttribute",
258 "GetHandleInformation",
259 "SetHandleInformation",
261 "VerifyConsoleIoHandle",
266 "CreateConsoleScreenBuffer",
267 "InvalidateBitMapRect",
268 "VDMConsoleOperation",
271 "ConsoleMenuControl",
273 "SetConsoleDisplayMode",
274 "RegisterConsoleVDM",
275 "GetConsoleHardwareState",
276 "SetConsoleHardwareState",
277 "GetConsoleDisplayMode",
280 "GetConsoleAliasesLength",
281 "GetConsoleAliasExesLength",
283 "GetConsoleAliasExes",
284 "ExpungeConsoleCommandHistory",
285 "SetConsoleNumberOfCommands",
286 "GetConsoleCommandHistoryLength",
287 "GetConsoleCommandHistory",
288 "SetConsoleCommandHistoryMode",
291 "SetConsoleKeyShortcuts",
292 "SetConsoleMenuClose",
293 "ConsoleNotifyLastClose",
294 "GenerateConsoleCtrlEvent",
295 "GetConsoleKeyboardLayoutName",
297 "GetConsoleCharType",
298 "SetConsoleLocalEUDC",
299 "SetConsoleCursorMode",
300 "GetConsoleCursorMode",
301 "RegisterConsoleOS2",
302 "SetConsoleOS2OemFormat",
305 "RegisterConsoleIME",
306 "UnregisterConsoleIME",
307 // "QueryConsoleIME",
310 "GetConsoleSelectionInfo",
311 "GetConsoleProcessList",
315 // "SetConsoleCurrentFont",
316 // "SetScreenBufferInfo",
317 // "ConsoleClientConnect",
321 /* FUNCTIONS ******************************************************************/
325 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
326 IN PCONSOLE_PROCESS_DATA TargetProcessData
);
330 ConSrvNewProcess(PCSR_PROCESS SourceProcess
,
331 PCSR_PROCESS TargetProcess
)
333 /**************************************************************************
334 * This function is called whenever a new process (GUI or CUI) is created.
336 * Copy the parent's handles table here if both the parent and the child
337 * processes are CUI. If we must actually create our proper console (and
338 * thus do not inherit from the console handles of the parent's), then we
339 * will clean this table in the next ConSrvConnect call. Why we are doing
340 * this? It's because here, we still don't know whether or not we must create
341 * a new console instead of inherit it from the parent, and, because in
342 * ConSrvConnect we don't have any reference to the parent process anymore.
343 **************************************************************************/
345 NTSTATUS Status
= STATUS_SUCCESS
;
346 PCONSOLE_PROCESS_DATA TargetProcessData
;
348 /* An empty target process is invalid */
349 if (!TargetProcess
) return STATUS_INVALID_PARAMETER
;
351 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
353 /* Initialize the new (target) process */
354 RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
355 TargetProcessData
->Process
= TargetProcess
;
356 TargetProcessData
->InputWaitHandle
= NULL
;
357 TargetProcessData
->ConsoleHandle
= TargetProcessData
->ParentConsoleHandle
= NULL
;
358 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
361 * The handles table gets initialized either when inheriting from
362 * another console process, or when creating a new console.
364 TargetProcessData
->HandleTableSize
= 0;
365 TargetProcessData
->HandleTable
= NULL
;
367 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
369 /* Do nothing if the source process is NULL */
370 if (!SourceProcess
) return STATUS_SUCCESS
;
372 // SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
375 * If the child process is a console application and the parent process is
376 * either a console application or just has a valid console (with a valid
377 * handles table: this can happen if it is a GUI application having called
378 * AllocConsole), then try to inherit handles from the parent process.
380 if (TargetProcessData
->ConsoleApp
/* && SourceProcessData->ConsoleApp */)
382 PCONSOLE_PROCESS_DATA SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
383 PCONSOLE SourceConsole
;
385 /* Validate and lock the parent's console */
386 if (ConSrvValidateConsole(&SourceConsole
,
387 SourceProcessData
->ConsoleHandle
,
388 CONSOLE_RUNNING
, TRUE
))
390 /* Inherit the parent's handles table */
391 Status
= ConSrvInheritHandlesTable(SourceProcessData
, TargetProcessData
);
392 if (NT_SUCCESS(Status
))
394 /* Temporary save the parent's console too */
395 TargetProcessData
->ParentConsoleHandle
= SourceProcessData
->ConsoleHandle
;
398 /* Unlock the parent's console */
399 LeaveCriticalSection(&SourceConsole
->Lock
);
408 ConSrvConnect(IN PCSR_PROCESS CsrProcess
,
409 IN OUT PVOID ConnectionInfo
,
410 IN OUT PULONG ConnectionInfoLength
)
412 /**************************************************************************
413 * This function is called whenever a CUI new process is created.
414 **************************************************************************/
416 NTSTATUS Status
= STATUS_SUCCESS
;
417 PCONSRV_API_CONNECTINFO ConnectInfo
= (PCONSRV_API_CONNECTINFO
)ConnectionInfo
;
418 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
420 if ( ConnectionInfo
== NULL
||
421 ConnectionInfoLength
== NULL
||
422 *ConnectionInfoLength
!= sizeof(CONSRV_API_CONNECTINFO
) )
424 DPRINT1("CONSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), wanted %lu\n",
426 ConnectionInfoLength
,
427 ConnectionInfoLength
? *ConnectionInfoLength
: (ULONG
)-1,
428 sizeof(CONSRV_API_CONNECTINFO
));
429 return STATUS_UNSUCCESSFUL
;
432 /* If we don't need a console, then get out of here */
433 if (!ConnectInfo
->ConsoleStartInfo
.ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
435 return STATUS_SUCCESS
;
438 /* If we don't have a console, then create a new one... */
439 if (!ConnectInfo
->ConsoleHandle
||
440 ConnectInfo
->ConsoleHandle
!= ProcessData
->ParentConsoleHandle
)
442 DPRINT("ConSrvConnect - Allocate a new console\n");
445 * We are about to create a new console. However when ConSrvNewProcess
446 * was called, we didn't know that we wanted to create a new console and
447 * therefore, we by default inherited the handles table from our parent
448 * process. It's only now that we notice that in fact we do not need
449 * them, because we've created a new console and thus we must use it.
451 * ConSrvAllocateConsole will free our old handles table
452 * and recreate a new valid one.
455 /* Initialize a new Console owned by the Console Leader Process */
456 Status
= ConSrvAllocateConsole(ProcessData
,
457 &ConnectInfo
->InputHandle
,
458 &ConnectInfo
->OutputHandle
,
459 &ConnectInfo
->ErrorHandle
,
460 &ConnectInfo
->ConsoleStartInfo
);
461 if (!NT_SUCCESS(Status
))
463 DPRINT1("Console allocation failed\n");
467 else /* We inherit it from the parent */
469 DPRINT("ConSrvConnect - Reuse current (parent's) console\n");
471 /* Reuse our current console */
472 Status
= ConSrvInheritConsole(ProcessData
,
473 ConnectInfo
->ConsoleHandle
,
475 NULL
, // &ConnectInfo->InputHandle,
476 NULL
, // &ConnectInfo->OutputHandle,
477 NULL
); // &ConnectInfo->ErrorHandle);
478 if (!NT_SUCCESS(Status
))
480 DPRINT1("Console inheritance failed\n");
485 /* Return the console handle and the input wait handle to the caller */
486 ConnectInfo
->ConsoleHandle
= ProcessData
->ConsoleHandle
;
487 ConnectInfo
->InputWaitHandle
= ProcessData
->InputWaitHandle
;
489 /* Set the Property-Dialog and Control-Dispatcher handlers */
490 ProcessData
->PropDispatcher
= ConnectInfo
->ConsoleStartInfo
.PropDispatcher
;
491 ProcessData
->CtrlDispatcher
= ConnectInfo
->ConsoleStartInfo
.CtrlDispatcher
;
493 return STATUS_SUCCESS
;
498 ConSrvDisconnect(PCSR_PROCESS Process
)
500 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
502 /**************************************************************************
503 * This function is called whenever a new process (GUI or CUI) is destroyed.
504 **************************************************************************/
506 if ( ProcessData
->ConsoleHandle
!= NULL
||
507 ProcessData
->HandleTable
!= NULL
)
509 DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
510 ConSrvRemoveConsole(ProcessData
);
513 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
516 CSR_SERVER_DLL_INIT(ConServerDllInitialization
)
518 /* Initialize the memory */
519 ConSrvHeap
= RtlGetProcessHeap();
521 // We can use our own heap instead of the CSR heap to investigate heap corruptions :)
522 ConSrvHeap = RtlCreateHeap(HEAP_GROWABLE |
523 HEAP_PROTECTION_ENABLED |
524 HEAP_FREE_CHECKING_ENABLED |
525 HEAP_TAIL_CHECKING_ENABLED |
526 HEAP_VALIDATE_ALL_ENABLED,
527 NULL, 0, 0, NULL, NULL);
528 if (!ConSrvHeap) return STATUS_NO_MEMORY;
531 ConDrvInitConsoleSupport();
532 ConSrvInitConsoleSupport();
534 /* Setup the DLL Object */
535 LoadedServerDll
->ApiBase
= CONSRV_FIRST_API_NUMBER
;
536 LoadedServerDll
->HighestApiSupported
= ConsolepMaxApiNumber
;
537 LoadedServerDll
->DispatchTable
= ConsoleServerApiDispatchTable
;
538 LoadedServerDll
->ValidTable
= ConsoleServerApiServerValidTable
;
540 LoadedServerDll
->NameTable
= ConsoleServerApiNameTable
;
542 LoadedServerDll
->SizeOfProcessData
= sizeof(CONSOLE_PROCESS_DATA
);
543 LoadedServerDll
->ConnectCallback
= ConSrvConnect
;
544 LoadedServerDll
->DisconnectCallback
= ConSrvDisconnect
;
545 LoadedServerDll
->NewProcessCallback
= ConSrvNewProcess
;
546 // LoadedServerDll->HardErrorCallback = ConSrvHardError;
547 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
549 ConSrvDllInstance
= LoadedServerDll
->ServerHandle
;
552 return STATUS_SUCCESS
;