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
,
112 IN PUNICODE_STRING ImagePathName
)
117 /* Get the startup information */
118 GetStartupInfoW(&si
);
120 /* Initialize the fields */
121 ConsoleStartInfo
->dwStartupFlags
= si
.dwFlags
;
122 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
124 ConsoleStartInfo
->FillAttribute
= si
.dwFillAttribute
;
126 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
128 ConsoleStartInfo
->ScreenBufferSize
.X
= (SHORT
)(si
.dwXCountChars
);
129 ConsoleStartInfo
->ScreenBufferSize
.Y
= (SHORT
)(si
.dwYCountChars
);
131 if (si
.dwFlags
& STARTF_USESHOWWINDOW
)
133 ConsoleStartInfo
->ShowWindow
= si
.wShowWindow
;
135 if (si
.dwFlags
& STARTF_USEPOSITION
)
137 ConsoleStartInfo
->ConsoleWindowOrigin
.x
= (LONG
)(si
.dwX
);
138 ConsoleStartInfo
->ConsoleWindowOrigin
.y
= (LONG
)(si
.dwY
);
140 if (si
.dwFlags
& STARTF_USESIZE
)
142 ConsoleStartInfo
->ConsoleWindowSize
.cx
= (LONG
)(si
.dwXSize
);
143 ConsoleStartInfo
->ConsoleWindowSize
.cy
= (LONG
)(si
.dwYSize
);
146 /* Set up the title for the console */
149 wcsncpy(ConsoleStartInfo
->ConsoleTitle
, si
.lpTitle
, MAX_PATH
+ 1);
153 ConsoleStartInfo
->ConsoleTitle
[0] = L
'\0';
156 /* Retrieve the application path name */
157 Length
= min(sizeof(ConsoleStartInfo
->AppPath
) / sizeof(ConsoleStartInfo
->AppPath
[0]) - 1,
158 ImagePathName
->Length
/ sizeof(WCHAR
));
159 wcsncpy(ConsoleStartInfo
->AppPath
, ImagePathName
->Buffer
, Length
);
160 ConsoleStartInfo
->AppPath
[Length
] = L
'\0';
162 /* The Console Server will use these fields to set up the console icon */
163 ConsoleStartInfo
->IconPath
[0] = L
'\0';
164 ConsoleStartInfo
->IconIndex
= 0;
170 BasepInitConsole(VOID
)
173 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
174 WCHAR SessionDir
[256];
175 ULONG SessionId
= NtCurrentPeb()->SessionId
;
178 CONSRV_API_CONNECTINFO ConnectInfo
;
179 ULONG ConnectInfoSize
= sizeof(ConnectInfo
);
181 DPRINT("BasepInitConsole for : %wZ\n", &Parameters
->ImagePathName
);
182 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
183 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
184 Parameters
->StandardOutput
, Parameters
->StandardError
);
186 /* Initialize our global console DLL lock */
187 Status
= RtlInitializeCriticalSection(&ConsoleLock
);
188 if (!NT_SUCCESS(Status
)) return FALSE
;
189 ConsoleInitialized
= TRUE
;
191 /* Do nothing if this isn't a console app... */
192 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
193 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
195 DPRINT("Image is not a console application\n");
196 Parameters
->ConsoleHandle
= NULL
;
197 ConnectInfo
.ConsoleNeeded
= FALSE
; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
199 ConnectInfo
.ConsoleStartInfo
.ConsoleTitle
[0] = L
'\0';
200 ConnectInfo
.ConsoleStartInfo
.AppPath
[0] = L
'\0';
206 InitConsoleInfo(&ConnectInfo
.ConsoleStartInfo
,
207 &Parameters
->ImagePathName
);
209 /* Initialize Input EXE name */
210 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
211 if (ExeName
) SetConsoleInputExeNameW(ExeName
+ 1);
213 /* Assume one is needed */
214 ConnectInfo
.ConsoleNeeded
= TRUE
;
216 /* Handle the special flags given to us by BasePushProcessParameters */
217 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
219 /* No console to create */
220 DPRINT("No console to create\n");
221 Parameters
->ConsoleHandle
= NULL
;
222 ConnectInfo
.ConsoleNeeded
= FALSE
;
224 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
226 /* We'll get the real one soon */
227 DPRINT("Creating new console\n");
228 Parameters
->ConsoleHandle
= NULL
;
230 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
232 /* We'll get the real one soon */
233 DPRINT("Creating new invisible console\n");
234 Parameters
->ConsoleHandle
= NULL
;
235 ConnectInfo
.ConsoleStartInfo
.ShowWindow
= SW_HIDE
;
239 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
241 Parameters
->ConsoleHandle
= NULL
;
243 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
247 /* Now use the proper console handle */
248 ConnectInfo
.ConsoleHandle
= Parameters
->ConsoleHandle
;
250 /* Initialize the Console Ctrl Handler */
251 InitConsoleCtrlHandling();
252 ConnectInfo
.CtrlDispatcher
= ConsoleControlDispatcher
;
254 /* Initialize the Property Dialog Handler */
255 ConnectInfo
.PropDispatcher
= PropDialogHandler
;
257 /* Setup the right Object Directory path */
260 /* Use the raw path */
261 wcscpy(SessionDir
, WIN_OBJ_DIR
);
265 /* Use the session path */
273 /* Connect to the Console Server */
274 DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
275 Status
= CsrClientConnectToServer(SessionDir
,
276 CONSRV_SERVERDLL_INDEX
,
280 if (!NT_SUCCESS(Status
))
282 DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status
);
286 /* Nothing to do for server-to-server */
287 if (InServer
) return TRUE
;
289 /* Nothing to do if not a console app */
290 if (!ConnectInfo
.ConsoleNeeded
) return TRUE
;
292 /* We got the handles, let's set them */
293 if ((Parameters
->ConsoleHandle
= ConnectInfo
.ConsoleHandle
))
295 /* If we already had some, don't use the new ones */
296 if (!Parameters
->StandardInput
)
298 Parameters
->StandardInput
= ConnectInfo
.InputHandle
;
300 if (!Parameters
->StandardOutput
)
302 Parameters
->StandardOutput
= ConnectInfo
.OutputHandle
;
304 if (!Parameters
->StandardError
)
306 Parameters
->StandardError
= ConnectInfo
.ErrorHandle
;
310 InputWaitHandle
= ConnectInfo
.InputWaitHandle
;
312 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
313 Parameters
->ConsoleHandle
,
314 Parameters
->StandardInput
,
315 Parameters
->StandardOutput
,
316 Parameters
->StandardError
);
323 BasepUninitConsole(VOID
)
325 /* Delete our critical section if we were initialized */
326 if (ConsoleInitialized
== TRUE
)
328 if (ConsoleLibrary
) FreeLibrary(ConsoleLibrary
);
330 ConsoleInitialized
= FALSE
;
331 RtlDeleteCriticalSection(&ConsoleLock
);