xref: /reactos/win32ss/user/winsrv/consrv/init.c (revision 5100859e)
1 /*
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)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "consrv.h"
12 
13 #include "api.h"
14 #include "procinit.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 PCSR_API_ROUTINE ConsoleServerApiDispatchTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
28 {
29     SrvOpenConsole,
30     SrvGetConsoleInput,
31     SrvWriteConsoleInput,
32     SrvReadConsoleOutput,
33     SrvWriteConsoleOutput,
34     SrvReadConsoleOutputString,
35     SrvWriteConsoleOutputString,
36     SrvFillConsoleOutput,
37     SrvGetConsoleMode,
38     SrvGetConsoleNumberOfFonts,
39     SrvGetConsoleNumberOfInputEvents,
40     SrvGetConsoleScreenBufferInfo,
41     SrvGetConsoleCursorInfo,
42     SrvGetConsoleMouseInfo,
43     SrvGetConsoleFontInfo,
44     SrvGetConsoleFontSize,
45     SrvGetConsoleCurrentFont,
46     SrvSetConsoleMode,
47     SrvSetConsoleActiveScreenBuffer,
48     SrvFlushConsoleInputBuffer,
49     SrvGetLargestConsoleWindowSize,
50     SrvSetConsoleScreenBufferSize,
51     SrvSetConsoleCursorPosition,
52     SrvSetConsoleCursorInfo,
53     SrvSetConsoleWindowInfo,
54     SrvScrollConsoleScreenBuffer,
55     SrvSetConsoleTextAttribute,
56     SrvSetConsoleFont,
57     SrvSetConsoleIcon,
58     SrvReadConsole,
59     SrvWriteConsole,
60     SrvDuplicateHandle,
61     SrvGetHandleInformation,
62     SrvSetHandleInformation,
63     SrvCloseHandle,
64     SrvVerifyConsoleIoHandle,
65     SrvAllocConsole,                        // Not present in Win7
66     SrvFreeConsole,                         // Not present in Win7
67     SrvGetConsoleTitle,
68     SrvSetConsoleTitle,
69     SrvCreateConsoleScreenBuffer,
70     SrvInvalidateBitMapRect,
71     SrvVDMConsoleOperation,
72     SrvSetConsoleCursor,
73     SrvShowConsoleCursor,
74     SrvConsoleMenuControl,
75     SrvSetConsolePalette,
76     SrvSetConsoleDisplayMode,
77     SrvRegisterConsoleVDM,
78     SrvGetConsoleHardwareState,
79     SrvSetConsoleHardwareState,
80     SrvGetConsoleDisplayMode,
81     SrvAddConsoleAlias,
82     SrvGetConsoleAlias,
83     SrvGetConsoleAliasesLength,
84     SrvGetConsoleAliasExesLength,
85     SrvGetConsoleAliases,
86     SrvGetConsoleAliasExes,
87     SrvExpungeConsoleCommandHistory,
88     SrvSetConsoleNumberOfCommands,
89     SrvGetConsoleCommandHistoryLength,
90     SrvGetConsoleCommandHistory,
91     SrvSetConsoleCommandHistoryMode,     // Not present in Vista+
92     SrvGetConsoleCP,
93     SrvSetConsoleCP,
94     SrvSetConsoleKeyShortcuts,
95     SrvSetConsoleMenuClose,
96     SrvConsoleNotifyLastClose,
97     SrvGenerateConsoleCtrlEvent,
98     SrvGetConsoleKeyboardLayoutName,
99     SrvGetConsoleWindow,
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
111     SrvGetConsoleLangId,
112     SrvAttachConsole,                       // Not present in Win7
113     SrvGetConsoleSelectionInfo,
114     SrvGetConsoleProcessList,
115 
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
121 };
122 
123 BOOLEAN ConsoleServerApiServerValidTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
124 {
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,
211 
212     FALSE,   // SrvGetConsoleHistory,
213     FALSE,   // SrvSetConsoleHistory
214     // FALSE,   // SrvSetConsoleCurrentFont,
215     // FALSE,   // SrvSetScreenBufferInfo,
216     // FALSE,   // SrvConsoleClientConnect,
217 };
218 
219 /*
220  * On Windows Server 2003, CSR Servers contain
221  * the API Names Table only in Debug Builds.
222  */
223 #ifdef CSR_DBG
224 PCHAR ConsoleServerApiNameTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER] =
225 {
226     "OpenConsole",
227     "GetConsoleInput",
228     "WriteConsoleInput",
229     "ReadConsoleOutput",
230     "WriteConsoleOutput",
231     "ReadConsoleOutputString",
232     "WriteConsoleOutputString",
233     "FillConsoleOutput",
234     "GetConsoleMode",
235     "GetConsoleNumberOfFonts",
236     "GetConsoleNumberOfInputEvents",
237     "GetConsoleScreenBufferInfo",
238     "GetConsoleCursorInfo",
239     "GetConsoleMouseInfo",
240     "GetConsoleFontInfo",
241     "GetConsoleFontSize",
242     "GetConsoleCurrentFont",
243     "SetConsoleMode",
244     "SetConsoleActiveScreenBuffer",
245     "FlushConsoleInputBuffer",
246     "GetLargestConsoleWindowSize",
247     "SetConsoleScreenBufferSize",
248     "SetConsoleCursorPosition",
249     "SetConsoleCursorInfo",
250     "SetConsoleWindowInfo",
251     "ScrollConsoleScreenBuffer",
252     "SetConsoleTextAttribute",
253     "SetConsoleFont",
254     "SetConsoleIcon",
255     "ReadConsole",
256     "WriteConsole",
257     "DuplicateHandle",
258     "GetHandleInformation",
259     "SetHandleInformation",
260     "CloseHandle",
261     "VerifyConsoleIoHandle",
262     "AllocConsole",
263     "FreeConsole",
264     "GetConsoleTitle",
265     "SetConsoleTitle",
266     "CreateConsoleScreenBuffer",
267     "InvalidateBitMapRect",
268     "VDMConsoleOperation",
269     "SetConsoleCursor",
270     "ShowConsoleCursor",
271     "ConsoleMenuControl",
272     "SetConsolePalette",
273     "SetConsoleDisplayMode",
274     "RegisterConsoleVDM",
275     "GetConsoleHardwareState",
276     "SetConsoleHardwareState",
277     "GetConsoleDisplayMode",
278     "AddConsoleAlias",
279     "GetConsoleAlias",
280     "GetConsoleAliasesLength",
281     "GetConsoleAliasExesLength",
282     "GetConsoleAliases",
283     "GetConsoleAliasExes",
284     "ExpungeConsoleCommandHistory",
285     "SetConsoleNumberOfCommands",
286     "GetConsoleCommandHistoryLength",
287     "GetConsoleCommandHistory",
288     "SetConsoleCommandHistoryMode",
289     "GetConsoleCP",
290     "SetConsoleCP",
291     "SetConsoleKeyShortcuts",
292     "SetConsoleMenuClose",
293     "ConsoleNotifyLastClose",
294     "GenerateConsoleCtrlEvent",
295     "GetConsoleKeyboardLayoutName",
296     "GetConsoleWindow",
297     "GetConsoleCharType",
298     "SetConsoleLocalEUDC",
299     "SetConsoleCursorMode",
300     "GetConsoleCursorMode",
301     "RegisterConsoleOS2",
302     "SetConsoleOS2OemFormat",
303     "GetConsoleNlsMode",
304     "SetConsoleNlsMode",
305     "RegisterConsoleIME",
306     "UnregisterConsoleIME",
307     // "QueryConsoleIME",
308     "GetConsoleLangId",
309     "AttachConsole",
310     "GetConsoleSelectionInfo",
311     "GetConsoleProcessList",
312 
313     "GetConsoleHistory",
314     "SetConsoleHistory",
315     // "SetConsoleCurrentFont",
316     // "SetScreenBufferInfo",
317     // "ConsoleClientConnect",
318 };
319 #endif
320 
321 /* FUNCTIONS ******************************************************************/
322 
323 /* See handle.c */
324 NTSTATUS
325 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
326                           IN PCONSOLE_PROCESS_DATA TargetProcessData);
327 
328 NTSTATUS
329 NTAPI
330 ConSrvNewProcess(PCSR_PROCESS SourceProcess,
331                  PCSR_PROCESS TargetProcess)
332 {
333     /**************************************************************************
334      * This function is called whenever a new process (GUI or CUI) is created.
335      *
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      **************************************************************************/
344 
345     NTSTATUS Status = STATUS_SUCCESS;
346     PCONSOLE_PROCESS_DATA TargetProcessData;
347 
348     /* An empty target process is invalid */
349     if (!TargetProcess) return STATUS_INVALID_PARAMETER;
350 
351     TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
352 
353     /* Initialize the new (target) process */
354     RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
355     TargetProcessData->Process = TargetProcess;
356     TargetProcessData->ConsoleHandle = NULL;
357     TargetProcessData->ConsoleApp = FALSE;
358 
359     /*
360      * The handles table gets initialized either when inheriting from
361      * another console process, or when creating a new console.
362      */
363     TargetProcessData->HandleTableSize = 0;
364     TargetProcessData->HandleTable = NULL;
365 
366     RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
367 
368     /* Do nothing if the source process is NULL */
369     if (!SourceProcess) return STATUS_SUCCESS;
370 
371     // SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
372 
373     /*
374      * If the child process is a console application and the parent process is
375      * either a console application or just has a valid console (with a valid
376      * handles table: this can happen if it is a GUI application having called
377      * AllocConsole), then try to inherit handles from the parent process.
378      */
379     if (TargetProcess->Flags & CsrProcessIsConsoleApp /* && SourceProcessData->ConsoleHandle != NULL */)
380     {
381         PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
382         PCONSRV_CONSOLE SourceConsole;
383 
384         /* Validate and lock the parent's console */
385         if (ConSrvValidateConsole(&SourceConsole,
386                                   SourceProcessData->ConsoleHandle,
387                                   CONSOLE_RUNNING, TRUE))
388         {
389             /* Inherit the parent's handles table */
390             Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
391             if (!NT_SUCCESS(Status))
392             {
393                 DPRINT1("Inheriting handles table failed\n");
394             }
395 
396             /* Unlock the parent's console */
397             LeaveCriticalSection(&SourceConsole->Lock);
398         }
399     }
400 
401     return Status;
402 }
403 
404 NTSTATUS
405 NTAPI
406 ConSrvConnect(IN PCSR_PROCESS CsrProcess,
407               IN OUT PVOID ConnectionInfo,
408               IN OUT PULONG ConnectionInfoLength)
409 {
410     /**************************************************************************
411      * This function is called whenever a CUI new process is created.
412      **************************************************************************/
413 
414     NTSTATUS Status = STATUS_SUCCESS;
415     PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo;
416     PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
417 
418     if ( ConnectionInfo       == NULL ||
419          ConnectionInfoLength == NULL ||
420         *ConnectionInfoLength != sizeof(*ConnectInfo) )
421     {
422         DPRINT1("CONSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), expected %lu\n",
423                 ConnectionInfo,
424                 ConnectionInfoLength,
425                 ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1,
426                 sizeof(*ConnectInfo));
427 
428         return STATUS_UNSUCCESSFUL;
429     }
430 
431     /* If we don't need a console, then get out of here */
432     DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False");
433     if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS;
434 
435     /* If we don't inherit from an existing console, then create a new one... */
436     if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL)
437     {
438         CONSOLE_INIT_INFO ConsoleInitInfo;
439 
440         DPRINT("ConSrvConnect - Allocate a new console\n");
441 
442         /* Initialize the console initialization info structure */
443         ConsoleInitInfo.ConsoleStartInfo = &ConnectInfo->ConsoleStartInfo;
444         ConsoleInitInfo.IsWindowVisible  = ConnectInfo->IsWindowVisible;
445         ConsoleInitInfo.TitleLength      = ConnectInfo->TitleLength;
446         ConsoleInitInfo.ConsoleTitle     = ConnectInfo->ConsoleTitle;
447         ConsoleInitInfo.DesktopLength    = 0;
448         ConsoleInitInfo.Desktop          = NULL;
449         ConsoleInitInfo.AppNameLength    = ConnectInfo->AppNameLength;
450         ConsoleInitInfo.AppName          = ConnectInfo->AppName;
451         ConsoleInitInfo.CurDirLength     = ConnectInfo->CurDirLength;
452         ConsoleInitInfo.CurDir           = ConnectInfo->CurDir;
453 
454         /*
455          * Contrary to the case of SrvAllocConsole, the desktop string is
456          * allocated in the process' heap, so we need to retrieve it by
457          * using NtReadVirtualMemory.
458          */
459         if (ConnectInfo->DesktopLength)
460         {
461             ConsoleInitInfo.DesktopLength = ConnectInfo->DesktopLength;
462 
463             ConsoleInitInfo.Desktop = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
464                                                        ConsoleInitInfo.DesktopLength);
465             if (ConsoleInitInfo.Desktop == NULL)
466                 return STATUS_NO_MEMORY;
467 
468             Status = NtReadVirtualMemory(ProcessData->Process->ProcessHandle,
469                                          ConnectInfo->Desktop,
470                                          ConsoleInitInfo.Desktop,
471                                          ConsoleInitInfo.DesktopLength,
472                                          NULL);
473             if (!NT_SUCCESS(Status))
474             {
475                 ConsoleFreeHeap(ConsoleInitInfo.Desktop);
476                 return Status;
477             }
478         }
479 
480         /*
481          * We are about to create a new console. However when ConSrvNewProcess
482          * was called, we didn't know that we wanted to create a new console and
483          * therefore, we by default inherited the handles table from our parent
484          * process. It's only now that we notice that in fact we do not need
485          * them, because we've created a new console and thus we must use it.
486          *
487          * ConSrvAllocateConsole will free our old handles table
488          * and recreate a new valid one.
489          */
490 
491         /* Initialize a new Console owned by the Console Leader Process */
492         Status = ConSrvAllocateConsole(ProcessData,
493                                        &ConnectInfo->ConsoleStartInfo.InputHandle,
494                                        &ConnectInfo->ConsoleStartInfo.OutputHandle,
495                                        &ConnectInfo->ConsoleStartInfo.ErrorHandle,
496                                        &ConsoleInitInfo);
497 
498         /* Free our local desktop string if any */
499         if (ConsoleInitInfo.DesktopLength)
500             ConsoleFreeHeap(ConsoleInitInfo.Desktop);
501 
502         /* Check for success */
503         if (!NT_SUCCESS(Status))
504         {
505             DPRINT1("Console allocation failed\n");
506             return Status;
507         }
508     }
509     else /* We inherit it from the parent */
510     {
511         DPRINT("ConSrvConnect - Reuse current (parent's) console\n");
512 
513         /* Reuse our current console */
514         Status = ConSrvInheritConsole(ProcessData,
515                                       ConnectInfo->ConsoleStartInfo.ConsoleHandle,
516                                       FALSE,
517                                       NULL, // &ConnectInfo->ConsoleStartInfo.InputHandle,
518                                       NULL, // &ConnectInfo->ConsoleStartInfo.OutputHandle,
519                                       NULL, // &ConnectInfo->ConsoleStartInfo.ErrorHandle,
520                                       &ConnectInfo->ConsoleStartInfo);
521         if (!NT_SUCCESS(Status))
522         {
523             DPRINT1("Console inheritance failed\n");
524             return Status;
525         }
526     }
527 
528     /* Set the Property-Dialog and Control-Dispatcher handlers */
529     ProcessData->PropRoutine = ConnectInfo->PropRoutine;
530     ProcessData->CtrlRoutine = ConnectInfo->CtrlRoutine;
531 
532     return STATUS_SUCCESS;
533 }
534 
535 VOID
536 NTAPI
537 ConSrvDisconnect(IN PCSR_PROCESS CsrProcess)
538 {
539     PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
540 
541     /**************************************************************************
542      * This function is called whenever a new process (GUI or CUI) is destroyed.
543      **************************************************************************/
544 
545     if ( ProcessData->ConsoleHandle != NULL ||
546          ProcessData->HandleTable   != NULL )
547     {
548         DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
549         ConSrvRemoveConsole(ProcessData);
550     }
551 
552     RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
553 }
554 
555 CSR_SERVER_DLL_INIT(ConServerDllInitialization)
556 {
557     /* Initialize the memory */
558     ConSrvHeap = RtlGetProcessHeap();
559 /*
560     // We can use our own heap instead of the CSR heap to investigate heap corruptions :)
561     ConSrvHeap = RtlCreateHeap(HEAP_GROWABLE                |
562                                HEAP_PROTECTION_ENABLED      |
563                                HEAP_FREE_CHECKING_ENABLED   |
564                                HEAP_TAIL_CHECKING_ENABLED   |
565                                HEAP_VALIDATE_ALL_ENABLED,
566                                NULL, 0, 0, NULL, NULL);
567     if (!ConSrvHeap) return STATUS_NO_MEMORY;
568 */
569 
570     ConDrvInitConsoleSupport();
571     ConSrvInitConsoleSupport();
572 
573     /* Setup the DLL Object */
574     LoadedServerDll->ApiBase = CONSRV_FIRST_API_NUMBER;
575     LoadedServerDll->HighestApiSupported = ConsolepMaxApiNumber;
576     LoadedServerDll->DispatchTable = ConsoleServerApiDispatchTable;
577     LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable;
578 #ifdef CSR_DBG
579     LoadedServerDll->NameTable = ConsoleServerApiNameTable;
580 #endif
581     LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA);
582     LoadedServerDll->ConnectCallback = ConSrvConnect;
583     LoadedServerDll->DisconnectCallback = ConSrvDisconnect;
584     LoadedServerDll->NewProcessCallback = ConSrvNewProcess;
585     // LoadedServerDll->HardErrorCallback = ConSrvHardError;
586     LoadedServerDll->ShutdownProcessCallback = ConsoleClientShutdown;
587 
588     ConSrvDllInstance = LoadedServerDll->ServerHandle;
589 
590     /* All done */
591     return STATUS_SUCCESS;
592 }
593 
594 /* EOF */
595