2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/console/init.c
5 * PURPOSE: Console API Client Initialization
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Aleksey Bragin (aleksey@reactos.org)
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
11 /* INCLUDES *******************************************************************/
15 // For Control Panel Applet
22 /* GLOBALS ********************************************************************/
24 RTL_CRITICAL_SECTION ConsoleLock
;
25 BOOL ConsoleInitialized
= FALSE
;
27 extern HANDLE InputWaitHandle
;
29 static HMODULE ConsoleLibrary
= NULL
;
30 static BOOL AlreadyDisplayingProps
= FALSE
;
32 #define WIN_OBJ_DIR L"\\Windows"
33 #define SESSION_DIR L"\\Sessions"
36 /* FUNCTIONS ******************************************************************/
40 PropDialogHandler(IN LPVOID lpThreadParameter
)
42 // NOTE: lpThreadParameter corresponds to the client shared section handle.
47 * Do not launch more than once the console property dialog applet,
48 * or (albeit less probable), if we are not initialized.
50 if (!ConsoleInitialized
|| AlreadyDisplayingProps
)
52 /* Close the associated client shared section handle if needed */
53 if (lpThreadParameter
)
55 CloseHandle((HANDLE
)lpThreadParameter
);
57 return STATUS_UNSUCCESSFUL
;
60 AlreadyDisplayingProps
= TRUE
;
62 /* Load the Control Applet if needed */
63 if (ConsoleLibrary
== NULL
)
65 WCHAR szBuffer
[MAX_PATH
];
67 GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
68 wcscat(szBuffer
, L
"\\system32\\console.dll");
69 ConsoleLibrary
= LoadLibraryW(szBuffer
);
71 if (ConsoleLibrary
== NULL
)
73 DPRINT1("Failed to load console.dll");
74 AlreadyDisplayingProps
= FALSE
;
75 return STATUS_UNSUCCESSFUL
;
79 /* Load its main function */
80 CPLFunc
= (APPLET_PROC
)GetProcAddress(ConsoleLibrary
, "CPlApplet");
83 DPRINT("Error: Console.dll misses CPlApplet export\n");
84 AlreadyDisplayingProps
= FALSE
;
85 return STATUS_UNSUCCESSFUL
;
88 if (CPLFunc(NULL
, CPL_INIT
, 0, 0) == FALSE
)
90 DPRINT("Error: failed to initialize console.dll\n");
91 AlreadyDisplayingProps
= FALSE
;
92 return STATUS_UNSUCCESSFUL
;
95 if (CPLFunc(NULL
, CPL_GETCOUNT
, 0, 0) != 1)
97 DPRINT("Error: console.dll returned unexpected CPL count\n");
98 AlreadyDisplayingProps
= FALSE
;
99 return STATUS_UNSUCCESSFUL
;
102 CPLFunc(NULL
, CPL_DBLCLK
, (LPARAM
)lpThreadParameter
, 0);
103 CPLFunc(NULL
, CPL_EXIT
, 0, 0);
105 AlreadyDisplayingProps
= FALSE
;
106 return STATUS_SUCCESS
;
111 InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo
)
115 GetStartupInfoW(&si
);
117 ConsoleStartInfo
->dwStartupFlags
= si
.dwFlags
;
118 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
120 ConsoleStartInfo
->FillAttribute
= si
.dwFillAttribute
;
122 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
124 ConsoleStartInfo
->ScreenBufferSize
.X
= (SHORT
)(si
.dwXCountChars
);
125 ConsoleStartInfo
->ScreenBufferSize
.Y
= (SHORT
)(si
.dwYCountChars
);
127 if (si
.dwFlags
& STARTF_USESHOWWINDOW
)
129 ConsoleStartInfo
->ShowWindow
= si
.wShowWindow
;
131 if (si
.dwFlags
& STARTF_USEPOSITION
)
133 ConsoleStartInfo
->ConsoleWindowOrigin
.x
= (LONG
)(si
.dwX
);
134 ConsoleStartInfo
->ConsoleWindowOrigin
.y
= (LONG
)(si
.dwY
);
136 if (si
.dwFlags
& STARTF_USESIZE
)
138 ConsoleStartInfo
->ConsoleWindowSize
.cx
= (LONG
)(si
.dwXSize
);
139 ConsoleStartInfo
->ConsoleWindowSize
.cy
= (LONG
)(si
.dwYSize
);
142 if (si.dwFlags & STARTF_RUNFULLSCREEN)
149 wcsncpy(ConsoleStartInfo
->ConsoleTitle
, si
.lpTitle
, MAX_PATH
+ 1);
153 ConsoleStartInfo
->ConsoleTitle
[0] = L
'\0';
160 BasepInitConsole(VOID
)
163 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
164 WCHAR SessionDir
[256];
165 ULONG SessionId
= NtCurrentPeb()->SessionId
;
168 CONSOLE_CONNECTION_INFO ConnectInfo
;
169 ULONG ConnectInfoSize
= sizeof(ConnectInfo
);
171 DPRINT("BasepInitConsole for : %wZ\n", &Parameters
->ImagePathName
);
172 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
173 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
174 Parameters
->StandardOutput
, Parameters
->StandardError
);
176 /* Initialize our global console DLL lock */
177 Status
= RtlInitializeCriticalSection(&ConsoleLock
);
178 if (!NT_SUCCESS(Status
)) return FALSE
;
179 ConsoleInitialized
= TRUE
;
181 /* Do nothing if this isn't a console app... */
182 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
183 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
185 DPRINT("Image is not a console application\n");
186 Parameters
->ConsoleHandle
= NULL
;
187 ConnectInfo
.ConsoleNeeded
= FALSE
; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
189 ConnectInfo
.ConsoleStartInfo
.ConsoleTitle
[0] = L
'\0';
190 ConnectInfo
.ConsoleStartInfo
.AppPath
[0] = L
'\0';
197 InitConsoleInfo(&ConnectInfo
.ConsoleStartInfo
);
199 Length
= min(sizeof(ConnectInfo
.ConsoleStartInfo
.AppPath
) / sizeof(ConnectInfo
.ConsoleStartInfo
.AppPath
[0]) - 1,
200 Parameters
->ImagePathName
.Length
/ sizeof(WCHAR
));
201 wcsncpy(ConnectInfo
.ConsoleStartInfo
.AppPath
, Parameters
->ImagePathName
.Buffer
, Length
);
202 ConnectInfo
.ConsoleStartInfo
.AppPath
[Length
] = L
'\0';
204 /* Initialize Input EXE name */
205 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
206 if (ExeName
) SetConsoleInputExeNameW(ExeName
+ 1);
208 /* Assume one is needed */
209 ConnectInfo
.ConsoleNeeded
= TRUE
;
211 /* Handle the special flags given to us by BasePushProcessParameters */
212 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
214 /* No console to create */
215 DPRINT("No console to create\n");
216 Parameters
->ConsoleHandle
= NULL
;
217 ConnectInfo
.ConsoleNeeded
= FALSE
;
219 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
221 /* We'll get the real one soon */
222 DPRINT("Creating new console\n");
223 Parameters
->ConsoleHandle
= NULL
;
225 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
227 /* We'll get the real one soon */
228 DPRINT("Creating new invisible console\n");
229 Parameters
->ConsoleHandle
= NULL
;
230 ConnectInfo
.ConsoleStartInfo
.ShowWindow
= SW_HIDE
;
234 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
236 Parameters
->ConsoleHandle
= NULL
;
238 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
242 /* Now use the proper console handle */
243 ConnectInfo
.Console
= Parameters
->ConsoleHandle
;
245 /* Initialize the Console Ctrl Handler */
246 InitConsoleCtrlHandling();
247 ConnectInfo
.CtrlDispatcher
= ConsoleControlDispatcher
;
249 /* Initialize the Property Dialog Handler */
250 ConnectInfo
.PropDispatcher
= PropDialogHandler
;
252 /* Setup the right Object Directory path */
255 /* Use the raw path */
256 wcscpy(SessionDir
, WIN_OBJ_DIR
);
260 /* Use the session path */
268 /* Connect to the Console Server */
269 DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
270 Status
= CsrClientConnectToServer(SessionDir
,
271 CONSRV_SERVERDLL_INDEX
,
275 if (!NT_SUCCESS(Status
))
277 DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status
);
281 /* Nothing to do for server-to-server */
282 if (InServer
) return TRUE
;
284 /* Nothing to do if not a console app */
285 if (!ConnectInfo
.ConsoleNeeded
) return TRUE
;
287 /* We got the handles, let's set them */
288 if ((Parameters
->ConsoleHandle
= ConnectInfo
.Console
))
290 /* If we already had some, don't use the new ones */
291 if (!Parameters
->StandardInput
)
293 Parameters
->StandardInput
= ConnectInfo
.InputHandle
;
295 if (!Parameters
->StandardOutput
)
297 Parameters
->StandardOutput
= ConnectInfo
.OutputHandle
;
299 if (!Parameters
->StandardError
)
301 Parameters
->StandardError
= ConnectInfo
.ErrorHandle
;
305 InputWaitHandle
= ConnectInfo
.InputWaitHandle
;
307 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
308 Parameters
->ConsoleHandle
,
309 Parameters
->StandardInput
,
310 Parameters
->StandardOutput
,
311 Parameters
->StandardError
);
318 BasepUninitConsole(VOID
)
320 /* Delete our critical section if we were initialized */
321 if (ConsoleInitialized
== TRUE
)
323 if (ConsoleLibrary
) FreeLibrary(ConsoleLibrary
);
325 ConsoleInitialized
= FALSE
;
326 RtlDeleteCriticalSection(&ConsoleLock
);