[CONSRV]
[reactos.git] / win32ss / user / consrv / init.c
1 /*
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)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "consrv.h"
12 #include "api.h"
13 #include "procinit.h"
14 #include "console.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* GLOBALS ********************************************************************/
20
21 HINSTANCE ConSrvDllInstance = NULL;
22
23 /* Memory */
24 HANDLE ConSrvHeap = NULL; // Our own heap.
25
26 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
27 // plus a little bit of Windows 7.
28 PCSR_API_ROUTINE ConsoleServerApiDispatchTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
29 {
30 SrvOpenConsole,
31 SrvGetConsoleInput,
32 SrvWriteConsoleInput,
33 SrvReadConsoleOutput,
34 SrvWriteConsoleOutput,
35 SrvReadConsoleOutputString,
36 SrvWriteConsoleOutputString,
37 SrvFillConsoleOutput,
38 SrvGetConsoleMode,
39 // SrvGetConsoleNumberOfFonts,
40 SrvGetConsoleNumberOfInputEvents,
41 SrvGetConsoleScreenBufferInfo,
42 SrvGetConsoleCursorInfo,
43 // SrvGetConsoleMouseInfo,
44 // SrvGetConsoleFontInfo,
45 // SrvGetConsoleFontSize,
46 // SrvGetConsoleCurrentFont,
47 SrvSetConsoleMode,
48 SrvSetConsoleActiveScreenBuffer,
49 SrvFlushConsoleInputBuffer,
50 SrvGetLargestConsoleWindowSize,
51 SrvSetConsoleScreenBufferSize,
52 SrvSetConsoleCursorPosition,
53 SrvSetConsoleCursorInfo,
54 SrvSetConsoleWindowInfo,
55 SrvScrollConsoleScreenBuffer,
56 SrvSetConsoleTextAttribute,
57 // SrvSetConsoleFont,
58 SrvSetConsoleIcon,
59 SrvReadConsole,
60 SrvWriteConsole,
61 SrvDuplicateHandle,
62 // SrvGetHandleInformation,
63 // SrvSetHandleInformation,
64 SrvCloseHandle,
65 SrvVerifyConsoleIoHandle,
66 SrvAllocConsole,
67 SrvFreeConsole,
68 SrvGetConsoleTitle,
69 SrvSetConsoleTitle,
70 SrvCreateConsoleScreenBuffer,
71 // SrvInvalidateBitMapRect,
72 // SrvVDMConsoleOperation,
73 // SrvSetConsoleCursor,
74 // SrvShowConsoleCursor,
75 // SrvConsoleMenuControl,
76 // SrvSetConsolePalette,
77 SrvSetConsoleDisplayMode,
78 // SrvRegisterConsoleVDM,
79 SrvGetConsoleHardwareState,
80 SrvSetConsoleHardwareState,
81 SrvGetConsoleDisplayMode,
82 SrvAddConsoleAlias,
83 SrvGetConsoleAlias,
84 SrvGetConsoleAliasesLength,
85 SrvGetConsoleAliasExesLength,
86 SrvGetConsoleAliases,
87 SrvGetConsoleAliasExes,
88 SrvExpungeConsoleCommandHistory,
89 SrvSetConsoleNumberOfCommands,
90 SrvGetConsoleCommandHistoryLength,
91 SrvGetConsoleCommandHistory,
92 // SrvSetConsoleCommandHistoryMode,
93 SrvGetConsoleCP,
94 SrvSetConsoleCP,
95 // SrvSetConsoleKeyShortcuts,
96 // SrvSetConsoleMenuClose,
97 // SrvConsoleNotifyLastClose,
98 SrvGenerateConsoleCtrlEvent,
99 // SrvGetConsoleKeyboardLayoutName,
100 SrvGetConsoleWindow,
101 // SrvGetConsoleCharType,
102 // SrvSetConsoleLocalEUDC,
103 // SrvSetConsoleCursorMode,
104 // SrvGetConsoleCursorMode,
105 // SrvRegisterConsoleOS2,
106 // SrvSetConsoleOS2OemFormat,
107 // SrvGetConsoleNlsMode,
108 // SrvSetConsoleNlsMode,
109 // SrvRegisterConsoleIME,
110 // SrvUnregisterConsoleIME,
111 // SrvGetConsoleLangId,
112 SrvAttachConsole,
113 SrvGetConsoleSelectionInfo,
114 SrvGetConsoleProcessList,
115 SrvGetConsoleHistory,
116 SrvSetConsoleHistory,
117 };
118
119 BOOLEAN ConsoleServerApiServerValidTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
120 {
121 FALSE, // SrvOpenConsole,
122 FALSE, // SrvGetConsoleInput,
123 FALSE, // SrvWriteConsoleInput,
124 FALSE, // SrvReadConsoleOutput,
125 FALSE, // SrvWriteConsoleOutput,
126 FALSE, // SrvReadConsoleOutputString,
127 FALSE, // SrvWriteConsoleOutputString,
128 FALSE, // SrvFillConsoleOutput,
129 FALSE, // SrvGetConsoleMode,
130 // FALSE, // SrvGetConsoleNumberOfFonts,
131 FALSE, // SrvGetConsoleNumberOfInputEvents,
132 FALSE, // SrvGetConsoleScreenBufferInfo,
133 FALSE, // SrvGetConsoleCursorInfo,
134 // FALSE, // SrvGetConsoleMouseInfo,
135 // FALSE, // SrvGetConsoleFontInfo,
136 // FALSE, // SrvGetConsoleFontSize,
137 // FALSE, // SrvGetConsoleCurrentFont,
138 FALSE, // SrvSetConsoleMode,
139 FALSE, // SrvSetConsoleActiveScreenBuffer,
140 FALSE, // SrvFlushConsoleInputBuffer,
141 FALSE, // SrvGetLargestConsoleWindowSize,
142 FALSE, // SrvSetConsoleScreenBufferSize,
143 FALSE, // SrvSetConsoleCursorPosition,
144 FALSE, // SrvSetConsoleCursorInfo,
145 FALSE, // SrvSetConsoleWindowInfo,
146 FALSE, // SrvScrollConsoleScreenBuffer,
147 FALSE, // SrvSetConsoleTextAttribute,
148 // FALSE, // SrvSetConsoleFont,
149 FALSE, // SrvSetConsoleIcon,
150 FALSE, // SrvReadConsole,
151 FALSE, // SrvWriteConsole,
152 FALSE, // SrvDuplicateHandle,
153 // FALSE, // SrvGetHandleInformation,
154 // FALSE, // SrvSetHandleInformation,
155 FALSE, // SrvCloseHandle,
156 FALSE, // SrvVerifyConsoleIoHandle,
157 FALSE, // SrvAllocConsole,
158 FALSE, // SrvFreeConsole,
159 FALSE, // SrvGetConsoleTitle,
160 FALSE, // SrvSetConsoleTitle,
161 FALSE, // SrvCreateConsoleScreenBuffer,
162 // FALSE, // SrvInvalidateBitMapRect,
163 // FALSE, // SrvVDMConsoleOperation,
164 // FALSE, // SrvSetConsoleCursor,
165 // FALSE, // SrvShowConsoleCursor,
166 // FALSE, // SrvConsoleMenuControl,
167 // FALSE, // SrvSetConsolePalette,
168 FALSE, // SrvSetConsoleDisplayMode,
169 // FALSE, // SrvRegisterConsoleVDM,
170 FALSE, // SrvGetConsoleHardwareState,
171 FALSE, // SrvSetConsoleHardwareState,
172 TRUE, // SrvGetConsoleDisplayMode,
173 FALSE, // SrvAddConsoleAlias,
174 FALSE, // SrvGetConsoleAlias,
175 FALSE, // SrvGetConsoleAliasesLength,
176 FALSE, // SrvGetConsoleAliasExesLength,
177 FALSE, // SrvGetConsoleAliases,
178 FALSE, // SrvGetConsoleAliasExes,
179 FALSE, // SrvExpungeConsoleCommandHistory,
180 FALSE, // SrvSetConsoleNumberOfCommands,
181 FALSE, // SrvGetConsoleCommandHistoryLength,
182 FALSE, // SrvGetConsoleCommandHistory,
183 // FALSE, // SrvSetConsoleCommandHistoryMode,
184 FALSE, // SrvGetConsoleCP,
185 FALSE, // SrvSetConsoleCP,
186 // FALSE, // SrvSetConsoleKeyShortcuts,
187 // FALSE, // SrvSetConsoleMenuClose,
188 // FALSE, // SrvConsoleNotifyLastClose,
189 FALSE, // SrvGenerateConsoleCtrlEvent,
190 // FALSE, // SrvGetConsoleKeyboardLayoutName,
191 FALSE, // SrvGetConsoleWindow,
192 // FALSE, // SrvGetConsoleCharType,
193 // FALSE, // SrvSetConsoleLocalEUDC,
194 // FALSE, // SrvSetConsoleCursorMode,
195 // FALSE, // SrvGetConsoleCursorMode,
196 // FALSE, // SrvRegisterConsoleOS2,
197 // FALSE, // SrvSetConsoleOS2OemFormat,
198 // FALSE, // SrvGetConsoleNlsMode,
199 // FALSE, // SrvSetConsoleNlsMode,
200 // FALSE, // SrvRegisterConsoleIME,
201 // FALSE, // SrvUnregisterConsoleIME,
202 // FALSE, // SrvGetConsoleLangId,
203 FALSE, // SrvAttachConsole,
204 FALSE, // SrvGetConsoleSelectionInfo,
205 FALSE, // SrvGetConsoleProcessList,
206 FALSE, // SrvGetConsoleHistory,
207 FALSE, // SrvSetConsoleHistory
208 };
209
210 PCHAR ConsoleServerApiNameTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
211 {
212 "OpenConsole",
213 "GetConsoleInput",
214 "WriteConsoleInput",
215 "ReadConsoleOutput",
216 "WriteConsoleOutput",
217 "ReadConsoleOutputString",
218 "WriteConsoleOutputString",
219 "FillConsoleOutput",
220 "GetConsoleMode",
221 // "GetConsoleNumberOfFonts",
222 "GetConsoleNumberOfInputEvents",
223 "GetConsoleScreenBufferInfo",
224 "GetConsoleCursorInfo",
225 // "GetConsoleMouseInfo",
226 // "GetConsoleFontInfo",
227 // "GetConsoleFontSize",
228 // "GetConsoleCurrentFont",
229 "SetConsoleMode",
230 "SetConsoleActiveScreenBuffer",
231 "FlushConsoleInputBuffer",
232 "GetLargestConsoleWindowSize",
233 "SetConsoleScreenBufferSize",
234 "SetConsoleCursorPosition",
235 "SetConsoleCursorInfo",
236 "SetConsoleWindowInfo",
237 "ScrollConsoleScreenBuffer",
238 "SetConsoleTextAttribute",
239 // "SetConsoleFont",
240 "SetConsoleIcon",
241 "ReadConsole",
242 "WriteConsole",
243 "DuplicateHandle",
244 // "GetHandleInformation",
245 // "SetHandleInformation",
246 "CloseHandle",
247 "VerifyConsoleIoHandle",
248 "AllocConsole",
249 "FreeConsole",
250 "GetConsoleTitle",
251 "SetConsoleTitle",
252 "CreateConsoleScreenBuffer",
253 // "InvalidateBitMapRect",
254 // "VDMConsoleOperation",
255 // "SetConsoleCursor",
256 // "ShowConsoleCursor",
257 // "ConsoleMenuControl",
258 // "SetConsolePalette",
259 "SetConsoleDisplayMode",
260 // "RegisterConsoleVDM",
261 "GetConsoleHardwareState",
262 "SetConsoleHardwareState",
263 "GetConsoleDisplayMode",
264 "AddConsoleAlias",
265 "GetConsoleAlias",
266 "GetConsoleAliasesLength",
267 "GetConsoleAliasExesLength",
268 "GetConsoleAliases",
269 "GetConsoleAliasExes",
270 "ExpungeConsoleCommandHistory",
271 "SetConsoleNumberOfCommands",
272 "GetConsoleCommandHistoryLength",
273 "GetConsoleCommandHistory",
274 // "SetConsoleCommandHistoryMode",
275 "GetConsoleCP",
276 "SetConsoleCP",
277 // "SetConsoleKeyShortcuts",
278 // "SetConsoleMenuClose",
279 // "ConsoleNotifyLastClose",
280 "GenerateConsoleCtrlEvent",
281 // "GetConsoleKeyboardLayoutName",
282 "GetConsoleWindow",
283 // "GetConsoleCharType",
284 // "SetConsoleLocalEUDC",
285 // "SetConsoleCursorMode",
286 // "GetConsoleCursorMode",
287 // "RegisterConsoleOS2",
288 // "SetConsoleOS2OemFormat",
289 // "GetConsoleNlsMode",
290 // "SetConsoleNlsMode",
291 // "RegisterConsoleIME",
292 // "UnregisterConsoleIME",
293 // "GetConsoleLangId",
294 "AttachConsole",
295 "GetConsoleSelectionInfo",
296 "GetConsoleProcessList",
297 "GetConsoleHistory",
298 "SetConsoleHistory",
299 };
300
301
302 /* FUNCTIONS ******************************************************************/
303
304 NTSTATUS
305 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
306 IN PCONSOLE_PROCESS_DATA TargetProcessData);
307
308 NTSTATUS
309 NTAPI
310 ConSrvNewProcess(PCSR_PROCESS SourceProcess,
311 PCSR_PROCESS TargetProcess)
312 {
313 /**************************************************************************
314 * This function is called whenever a new process (GUI or CUI) is created.
315 *
316 * Copy the parent's handles table here if both the parent and the child
317 * processes are CUI. If we must actually create our proper console (and
318 * thus do not inherit from the console handles of the parent's), then we
319 * will clean this table in the next ConSrvConnect call. Why we are doing
320 * this? It's because here, we still don't know whether or not we must create
321 * a new console instead of inherit it from the parent, and, because in
322 * ConSrvConnect we don't have any reference to the parent process anymore.
323 **************************************************************************/
324
325 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
326
327 /* An empty target process is invalid */
328 if (!TargetProcess) return STATUS_INVALID_PARAMETER;
329
330 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
331
332 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
333
334 /* Initialize the new (target) process */
335 TargetProcessData->Process = TargetProcess;
336 TargetProcessData->ConsoleEvent = NULL;
337 TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
338 TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
339
340 // Testing
341 TargetProcessData->HandleTableSize = 0;
342 TargetProcessData->HandleTable = NULL;
343
344 RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
345
346 /* Do nothing if the source process is NULL */
347 if (!SourceProcess) return STATUS_SUCCESS;
348
349 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
350
351 /*
352 * If both of the processes (parent and new child) are console applications,
353 * then try to inherit handles from the parent process.
354 */
355 if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
356 TargetProcessData->ConsoleApp )
357 {
358 NTSTATUS Status;
359
360 Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
361 if (!NT_SUCCESS(Status)) return Status;
362
363 /* Temporary save the parent's console */
364 TargetProcessData->ParentConsole = SourceProcessData->Console;
365 }
366
367 return STATUS_SUCCESS;
368 }
369
370 NTSTATUS
371 NTAPI
372 ConSrvConnect(IN PCSR_PROCESS CsrProcess,
373 IN OUT PVOID ConnectionInfo,
374 IN OUT PULONG ConnectionInfoLength)
375 {
376 /**************************************************************************
377 * This function is called whenever a CUI new process is created.
378 **************************************************************************/
379
380 NTSTATUS Status = STATUS_SUCCESS;
381 PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
382 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
383
384 if ( ConnectionInfo == NULL ||
385 ConnectionInfoLength == NULL ||
386 *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
387 {
388 DPRINT1("CONSRV: Connection failed\n");
389 return STATUS_UNSUCCESSFUL;
390 }
391
392 /* If we don't need a console, then get out of here */
393 if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
394 {
395 return STATUS_SUCCESS;
396 }
397
398 /* If we don't have a console, then create a new one... */
399 if (!ConnectInfo->Console ||
400 ConnectInfo->Console != ProcessData->ParentConsole)
401 {
402 DPRINT("ConSrvConnect - Allocate a new console\n");
403
404 /*
405 * We are about to create a new console. However when ConSrvNewProcess
406 * was called, we didn't know that we wanted to create a new console and
407 * therefore, we by default inherited the handles table from our parent
408 * process. It's only now that we notice that in fact we do not need
409 * them, because we've created a new console and thus we must use it.
410 *
411 * Therefore, free the console we can have and our handles table,
412 * and recreate a new one later on.
413 */
414 ConSrvRemoveConsole(ProcessData);
415
416 /* Initialize a new Console owned by the Console Leader Process */
417 Status = ConSrvAllocateConsole(ProcessData,
418 &ConnectInfo->InputHandle,
419 &ConnectInfo->OutputHandle,
420 &ConnectInfo->ErrorHandle,
421 &ConnectInfo->ConsoleStartInfo);
422 if (!NT_SUCCESS(Status))
423 {
424 DPRINT1("Console allocation failed\n");
425 return Status;
426 }
427 }
428 else /* We inherit it from the parent */
429 {
430 DPRINT("ConSrvConnect - Reuse current (parent's) console\n");
431
432 /* Reuse our current console */
433 Status = ConSrvInheritConsole(ProcessData,
434 ConnectInfo->Console,
435 FALSE,
436 NULL, // &ConnectInfo->InputHandle,
437 NULL, // &ConnectInfo->OutputHandle,
438 NULL); // &ConnectInfo->ErrorHandle);
439 if (!NT_SUCCESS(Status))
440 {
441 DPRINT1("Console inheritance failed\n");
442 return Status;
443 }
444 }
445
446 /* Return it to the caller */
447 ConnectInfo->Console = ProcessData->Console;
448
449 /* Input Wait Handle */
450 ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
451
452 /* Set the Property Dialog Handler */
453 ProcessData->PropDispatcher = ConnectInfo->PropDispatcher;
454
455 /* Set the Ctrl Dispatcher */
456 ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
457
458 return STATUS_SUCCESS;
459 }
460
461 VOID
462 NTAPI
463 ConSrvDisconnect(PCSR_PROCESS Process)
464 {
465 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
466
467 /**************************************************************************
468 * This function is called whenever a new process (GUI or CUI) is destroyed.
469 **************************************************************************/
470
471 if ( ProcessData->Console != NULL ||
472 ProcessData->HandleTable != NULL )
473 {
474 DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
475 ConSrvRemoveConsole(ProcessData);
476 }
477
478 RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
479 }
480
481 CSR_SERVER_DLL_INIT(ConServerDllInitialization)
482 {
483 /* Initialize the memory */
484 ConSrvHeap = RtlGetProcessHeap();
485
486 ConSrvInitConsoleSupport();
487
488 /* Setup the DLL Object */
489 LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER;
490 LoadedServerDll->HighestApiSupported = ConsolepMaxApiNumber;
491 LoadedServerDll->DispatchTable = ConsoleServerApiDispatchTable;
492 LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable;
493 LoadedServerDll->NameTable = ConsoleServerApiNameTable;
494 LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA);
495 LoadedServerDll->ConnectCallback = ConSrvConnect;
496 LoadedServerDll->DisconnectCallback = ConSrvDisconnect;
497 LoadedServerDll->NewProcessCallback = ConSrvNewProcess;
498 // LoadedServerDll->HardErrorCallback = ConSrvHardError;
499 LoadedServerDll->ShutdownProcessCallback = NULL;
500
501 ConSrvDllInstance = LoadedServerDll->ServerHandle;
502
503 /* All done */
504 return STATUS_SUCCESS;
505 }
506
507 BOOL
508 WINAPI
509 DllMain(IN HINSTANCE hInstanceDll,
510 IN DWORD dwReason,
511 IN LPVOID lpReserved)
512 {
513 UNREFERENCED_PARAMETER(hInstanceDll);
514 UNREFERENCED_PARAMETER(dwReason);
515 UNREFERENCED_PARAMETER(lpReserved);
516 return TRUE;
517 }
518
519 /* EOF */