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