Don't use CSRSS handles if we alreay have some (so we can inherit file handles, etc)
[reactos.git] / reactos / lib / kernel32 / misc / dllmain.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/dllmain.c
6 * PURPOSE: Initialization
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <k32.h>
15
16 #define NDEBUG
17 #include "../include/debug.h"
18
19 /* GLOBALS *******************************************************************/
20
21 extern UNICODE_STRING SystemDirectory;
22 extern UNICODE_STRING WindowsDirectory;
23
24 HANDLE hProcessHeap = NULL;
25 HMODULE hCurrentModule = NULL;
26 HANDLE hBaseDir = NULL;
27
28 static BOOL DllInitialized = FALSE;
29
30 BOOL STDCALL
31 DllMain(HANDLE hInst,
32 DWORD dwReason,
33 LPVOID lpReserved);
34
35 /* Critical section for various kernel32 data structures */
36 RTL_CRITICAL_SECTION DllLock;
37 RTL_CRITICAL_SECTION ConsoleLock;
38
39 extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
40 extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
41
42 extern BOOL FASTCALL NlsInit();
43 extern VOID FASTCALL NlsUninit();
44
45 HANDLE
46 STDCALL
47 DuplicateConsoleHandle(HANDLE hConsole,
48 DWORD dwDesiredAccess,
49 BOOL bInheritHandle,
50 DWORD dwOptions);
51
52 /* FUNCTIONS *****************************************************************/
53
54 static NTSTATUS
55 OpenBaseDirectory(PHANDLE DirHandle)
56 {
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\BaseNamedObjects");
59 NTSTATUS Status;
60
61 InitializeObjectAttributes(&ObjectAttributes,
62 &Name,
63 OBJ_PERMANENT,
64 NULL,
65 NULL);
66
67 Status = NtOpenDirectoryObject(DirHandle,
68 DIRECTORY_ALL_ACCESS,
69 &ObjectAttributes);
70 if (!NT_SUCCESS(Status))
71 {
72 Status = NtCreateDirectoryObject(DirHandle,
73 DIRECTORY_ALL_ACCESS,
74 &ObjectAttributes);
75 if (!NT_SUCCESS(Status))
76 {
77 DbgPrint("NtCreateDirectoryObject() failed\n");
78 }
79
80 return Status;
81 }
82
83 return STATUS_SUCCESS;
84 }
85
86 BOOL
87 STDCALL
88 BasepInitConsole(VOID)
89 {
90 CSR_API_MESSAGE Request;
91 ULONG CsrRequest;
92 NTSTATUS Status;
93 PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
94
95 WCHAR lpTest[MAX_PATH];
96 GetModuleFileNameW(NULL, lpTest, MAX_PATH);
97 DPRINT1("BasepInitConsole for : %S\n", lpTest);
98 DPRINT1("Our current console handles are: %lx, %lx, %lx\n",
99 Parameters->ConsoleHandle, Parameters->StandardInput,
100 Parameters->StandardOutput);
101
102 /* We have nothing to do if this isn't a console app... */
103 if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
104 IMAGE_SUBSYSTEM_WINDOWS_CUI)
105 {
106 DPRINT1("Image is not a console application\n");
107 Parameters->ConsoleHandle = NULL;
108 return TRUE;
109 }
110
111 /* Assume one is needed */
112 Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
113
114 /* Handle the special flags given to us by BasepInitializeEnvironment */
115 if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
116 {
117 /* No console to create */
118 DPRINT1("No console to create\n");
119 Parameters->ConsoleHandle = NULL;
120 Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
121 }
122 else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
123 {
124 /* We'll get the real one soon */
125 DPRINT1("Creating new console\n");
126 Parameters->ConsoleHandle = NULL;
127 }
128 else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
129 {
130 /* We'll get the real one soon */
131 DPRINT1("NOT SUPPORTED: HANDLE_CREATE_NO_WINDOW\n");
132 Parameters->ConsoleHandle = NULL;
133 }
134 else
135 {
136 DPRINT1("Using existing console: %x\n", Parameters->ConsoleHandle);
137 }
138
139 /* Initialize Console Ctrl Handler */
140 RtlInitializeCriticalSection(&ConsoleLock);
141 SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE);
142
143 /* Now use the proper console handle */
144 Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
145
146 /*
147 * Normally, we should be connecting to the Console CSR Server...
148 * but we don't have one yet, so we will instead simply send a create
149 * console message to the Base Server. When we finally have a Console
150 * Server, this code should be changed to send connection data instead.
151 *
152 * Also note that this connection should be made for any console app, even
153 * in the case above where -we- return.
154 */
155 CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
156 Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
157 Status = CsrClientCallServer(&Request,
158 NULL,
159 CsrRequest,
160 sizeof(CSR_API_MESSAGE));
161 if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
162 {
163 DPRINT1("CSR Failed to give us a console\n");
164 /* We're lying here, so at least the process can load... */
165 return TRUE;
166 }
167
168 /* We got the handles, let's set them */
169 Parameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console;
170
171 /* If we already had some, don't use the new ones */
172 if (!Parameters->StandardInput)
173 {
174 Parameters->StandardInput = Request.Data.AllocConsoleRequest.InputHandle;
175 }
176 if (!Parameters->StandardOutput)
177 {
178 Parameters->StandardOutput = Request.Data.AllocConsoleRequest.OutputHandle;
179 }
180 if (!Parameters->StandardError)
181 {
182 Parameters->StandardError = DuplicateConsoleHandle(Request.Data.AllocConsoleRequest.OutputHandle,
183 0,
184 TRUE,
185 DUPLICATE_SAME_ACCESS);
186 }
187
188 DPRINT1("Console setup: %lx, %lx, %lx\n",
189 Parameters->ConsoleHandle,
190 Parameters->StandardInput,
191 Parameters->StandardOutput);
192 return TRUE;
193 }
194
195
196 BOOL STDCALL
197 DllMain(HANDLE hDll,
198 DWORD dwReason,
199 LPVOID lpReserved)
200 {
201 NTSTATUS Status;
202
203 (void)lpReserved;
204
205 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
206 hDll, dwReason);
207
208 switch (dwReason)
209 {
210 case DLL_PROCESS_ATTACH:
211 DPRINT("DLL_PROCESS_ATTACH\n");
212
213 LdrDisableThreadCalloutsForDll ((PVOID)hDll);
214
215 /*
216 * Connect to the csrss server
217 */
218 Status = CsrClientConnectToServer(NULL,
219 0,
220 NULL,
221 NULL,
222 0,
223 NULL);
224 if (!NT_SUCCESS(Status))
225 {
226 DbgPrint("Failed to connect to csrss.exe (Status %lx)\n",
227 Status);
228 ZwTerminateProcess(NtCurrentProcess(), Status);
229 return FALSE;
230 }
231
232 hProcessHeap = RtlGetProcessHeap();
233 hCurrentModule = hDll;
234
235 /*
236 * Initialize WindowsDirectory and SystemDirectory
237 */
238 DPRINT("NtSystemRoot: %S\n",
239 SharedUserData->NtSystemRoot);
240 RtlCreateUnicodeString (&WindowsDirectory,
241 SharedUserData->NtSystemRoot);
242 SystemDirectory.MaximumLength = WindowsDirectory.MaximumLength + 18;
243 SystemDirectory.Length = WindowsDirectory.Length + 18;
244 SystemDirectory.Buffer = RtlAllocateHeap (hProcessHeap,
245 0,
246 SystemDirectory.MaximumLength);
247 wcscpy (SystemDirectory.Buffer, WindowsDirectory.Buffer);
248 wcscat (SystemDirectory.Buffer, L"\\System32");
249
250 /* Open object base directory */
251 Status = OpenBaseDirectory(&hBaseDir);
252 if (!NT_SUCCESS(Status))
253 {
254 DbgPrint("Failed to open object base directory (Status %lx)\n",
255 Status);
256 return FALSE;
257 }
258
259 /* Initialize the DLL critical section */
260 RtlInitializeCriticalSection(&DllLock);
261
262 /* Initialize the National Language Support routines */
263 if (! NlsInit())
264 {
265 return FALSE;
266 }
267
268 /* Initialize Console Support */
269 if (!BasepInitConsole())
270 {
271 DPRINT1("Failure to set up console\n");
272 return FALSE;
273 }
274
275 /* Insert more dll attach stuff here! */
276
277 DllInitialized = TRUE;
278 break;
279
280 case DLL_PROCESS_DETACH:
281 DPRINT("DLL_PROCESS_DETACH\n");
282 if (DllInitialized == TRUE)
283 {
284 /* Insert more dll detach stuff here! */
285
286 NlsUninit();
287
288 /* Delete DLL critical section */
289 RtlDeleteCriticalSection (&ConsoleLock);
290 RtlDeleteCriticalSection (&DllLock);
291
292 /* Close object base directory */
293 NtClose(hBaseDir);
294
295 RtlFreeUnicodeString (&SystemDirectory);
296 RtlFreeUnicodeString (&WindowsDirectory);
297 }
298 break;
299
300 default:
301 break;
302 }
303
304 return TRUE;
305 }
306
307 /* EOF */