... and kernel32, too.
[reactos.git] / reactos / dll / win32 / 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 <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 PPEB Peb;
28 ULONG SessionId;
29 BOOL ConsoleInitialized = FALSE;
30
31 static BOOL DllInitialized = FALSE;
32
33 BOOL WINAPI
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(VOID);
46 extern VOID FASTCALL NlsUninit(VOID);
47 BOOLEAN InWindows = FALSE;
48
49 HANDLE
50 WINAPI
51 DuplicateConsoleHandle(HANDLE hConsole,
52 DWORD dwDesiredAccess,
53 BOOL bInheritHandle,
54 DWORD dwOptions);
55
56 #define WIN_OBJ_DIR L"\\Windows"
57 #define SESSION_DIR L"\\Sessions"
58
59 SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
60
61 /* FUNCTIONS *****************************************************************/
62
63 NTSTATUS
64 WINAPI
65 OpenBaseDirectory(PHANDLE DirHandle)
66 {
67 OBJECT_ATTRIBUTES ObjectAttributes;
68 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\BaseNamedObjects");
69 NTSTATUS Status;
70
71 InitializeObjectAttributes(&ObjectAttributes,
72 &Name,
73 OBJ_CASE_INSENSITIVE,
74 NULL,
75 NULL);
76
77 Status = NtOpenDirectoryObject(DirHandle,
78 DIRECTORY_ALL_ACCESS &
79 ~(DELETE | WRITE_DAC | WRITE_OWNER),
80 &ObjectAttributes);
81 if (!NT_SUCCESS(Status))
82 {
83 return Status;
84 }
85
86 DPRINT("Opened BNO: %lx\n", *DirHandle);
87 return Status;
88 }
89
90 /*
91 * @unimplemented
92 */
93 BOOL
94 WINAPI
95 BaseQueryModuleData(IN LPSTR ModuleName,
96 IN LPSTR Unknown,
97 IN PVOID Unknown2,
98 IN PVOID Unknown3,
99 IN PVOID Unknown4)
100 {
101 DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n",
102 ModuleName,
103 Unknown,
104 Unknown2,
105 Unknown3,
106 Unknown4);
107 return FALSE;
108 }
109
110 /*
111 * @unimplemented
112 */
113 NTSTATUS
114 WINAPI
115 BaseProcessInitPostImport(VOID)
116 {
117 /* FIXME: Initialize TS pointers */
118 return STATUS_SUCCESS;
119 }
120
121 BOOL
122 WINAPI
123 BasepInitConsole(VOID)
124 {
125 CSR_API_MESSAGE Request;
126 ULONG CsrRequest;
127 NTSTATUS Status;
128 PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
129
130 WCHAR lpTest[MAX_PATH];
131 GetModuleFileNameW(NULL, lpTest, MAX_PATH);
132 DPRINT("BasepInitConsole for : %S\n", lpTest);
133 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
134 Parameters->ConsoleHandle, Parameters->StandardInput,
135 Parameters->StandardOutput, Parameters->StandardError);
136
137 /* We have nothing to do if this isn't a console app... */
138 if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
139 IMAGE_SUBSYSTEM_WINDOWS_CUI)
140 {
141 DPRINT("Image is not a console application\n");
142 Parameters->ConsoleHandle = NULL;
143 return TRUE;
144 }
145
146 /* Assume one is needed */
147 Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
148
149 /* Handle the special flags given to us by BasepInitializeEnvironment */
150 if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
151 {
152 /* No console to create */
153 DPRINT("No console to create\n");
154 Parameters->ConsoleHandle = NULL;
155 Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
156 }
157 else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
158 {
159 /* We'll get the real one soon */
160 DPRINT("Creating new console\n");
161 Parameters->ConsoleHandle = NULL;
162 }
163 else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
164 {
165 /* We'll get the real one soon */
166 DPRINT1("NOT SUPPORTED: HANDLE_CREATE_NO_WINDOW\n");
167 Parameters->ConsoleHandle = NULL;
168 }
169 else
170 {
171 if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
172 {
173 Parameters->ConsoleHandle = 0;
174 }
175 DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle);
176 }
177
178 /* Initialize Console Ctrl Handler */
179 ConsoleInitialized = TRUE;
180 RtlInitializeCriticalSection(&ConsoleLock);
181 SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE);
182
183 /* Now use the proper console handle */
184 Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
185
186 /*
187 * Normally, we should be connecting to the Console CSR Server...
188 * but we don't have one yet, so we will instead simply send a create
189 * console message to the Base Server. When we finally have a Console
190 * Server, this code should be changed to send connection data instead.
191 *
192 * Also note that this connection should be made for any console app, even
193 * in the case above where -we- return.
194 */
195 CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
196 Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
197 Status = CsrClientCallServer(&Request,
198 NULL,
199 CsrRequest,
200 sizeof(CSR_API_MESSAGE));
201 if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
202 {
203 DPRINT1("CSR Failed to give us a console\n");
204 /* We're lying here, so at least the process can load... */
205 return TRUE;
206 }
207
208 /* We got the handles, let's set them */
209 if ((Parameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console))
210 {
211 /* If we already had some, don't use the new ones */
212 if (!Parameters->StandardInput)
213 {
214 Parameters->StandardInput = Request.Data.AllocConsoleRequest.InputHandle;
215 }
216 if (!Parameters->StandardOutput)
217 {
218 Parameters->StandardOutput = Request.Data.AllocConsoleRequest.OutputHandle;
219 }
220 if (!Parameters->StandardError)
221 {
222 Parameters->StandardError = Request.Data.AllocConsoleRequest.OutputHandle;
223 }
224 }
225
226 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
227 Parameters->ConsoleHandle,
228 Parameters->StandardInput,
229 Parameters->StandardOutput,
230 Parameters->StandardError);
231 return TRUE;
232 }
233
234
235 BOOL
236 WINAPI
237 DllMain(HANDLE hDll,
238 DWORD dwReason,
239 LPVOID lpReserved)
240 {
241 NTSTATUS Status;
242 BOOLEAN IsServer;
243 ULONG Dummy;
244 ULONG DummySize = sizeof(Dummy);
245 WCHAR SessionDir[256];
246
247 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
248 hDll, dwReason);
249
250 Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
251
252 /* Cache the PEB and Session ID */
253 Peb = NtCurrentPeb();
254 SessionId = Peb->SessionId;
255
256 switch (dwReason)
257 {
258 case DLL_PROCESS_ATTACH:
259
260 /* Don't bother us for each thread */
261 LdrDisableThreadCalloutsForDll((PVOID)hDll);
262
263 /* Setup the right Object Directory path */
264 if (!SessionId)
265 {
266 /* Use the raw path */
267 wcscpy(SessionDir, WIN_OBJ_DIR);
268 }
269 else
270 {
271 /* Use the session path */
272 swprintf(SessionDir,
273 L"%ws\\%ld%ws",
274 SESSION_DIR,
275 SessionId,
276 WIN_OBJ_DIR);
277 }
278
279 /* Connect to the base server */
280 DPRINT("Connecting to CSR...\n");
281 Status = CsrClientConnectToServer(SessionDir,
282 InWindows ? 1 : 0,
283 &Dummy,
284 &DummySize,
285 &IsServer);
286 if (!NT_SUCCESS(Status))
287 {
288 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
289 ZwTerminateProcess(NtCurrentProcess(), Status);
290 return FALSE;
291 }
292
293 /* Check if we are running a CSR Server */
294 if (!IsServer)
295 {
296 /* Set the termination port for the thread */
297 DPRINT("Creating new thread for CSR\n");
298 CsrNewThread();
299 }
300
301 hProcessHeap = RtlGetProcessHeap();
302 RtlInitializeHandleTable(0xFFFF,
303 sizeof(BASE_HEAP_HANDLE_ENTRY),
304 &BaseHeapHandleTable);
305 hCurrentModule = hDll;
306 DPRINT("Heap: %p\n", hProcessHeap);
307
308 /*
309 * Initialize WindowsDirectory and SystemDirectory
310 */
311 DPRINT("NtSystemRoot: %S\n", SharedUserData->NtSystemRoot);
312 RtlCreateUnicodeString (&WindowsDirectory, SharedUserData->NtSystemRoot);
313 SystemDirectory.MaximumLength = WindowsDirectory.MaximumLength + 18;
314 SystemDirectory.Length = WindowsDirectory.Length + 18;
315 SystemDirectory.Buffer = RtlAllocateHeap(hProcessHeap,
316 0,
317 SystemDirectory.MaximumLength);
318 if(SystemDirectory.Buffer == NULL)
319 {
320 return FALSE;
321 }
322 wcscpy(SystemDirectory.Buffer, WindowsDirectory.Buffer);
323 wcscat(SystemDirectory.Buffer, L"\\System32");
324
325 /* Open object base directory */
326 Status = OpenBaseDirectory(&hBaseDir);
327 if (!NT_SUCCESS(Status))
328 {
329 DPRINT1("Failed to open object base directory (Status %lx)\n", Status);
330 return FALSE;
331 }
332
333 /* Initialize the DLL critical section */
334 RtlInitializeCriticalSection(&DllLock);
335
336 /* Initialize the National Language Support routines */
337 if (!NlsInit())
338 {
339 DPRINT1("NLS Init failed\n");
340 return FALSE;
341 }
342
343 /* Initialize Console Support */
344 if (!BasepInitConsole())
345 {
346 DPRINT1("Failure to set up console\n");
347 return FALSE;
348 }
349
350 /* Cache static system information */
351 Status = ZwQuerySystemInformation(SystemBasicInformation,
352 &BaseCachedSysInfo,
353 sizeof(BaseCachedSysInfo),
354 NULL);
355 if (!NT_SUCCESS(Status))
356 {
357 DPRINT1("Failure to get system information\n");
358 return FALSE;
359 }
360
361 /* Insert more dll attach stuff here! */
362 DllInitialized = TRUE;
363 DPRINT("Initialization complete\n");
364 break;
365
366 case DLL_PROCESS_DETACH:
367
368 DPRINT("DLL_PROCESS_DETACH\n");
369 if (DllInitialized == TRUE)
370 {
371 /* Insert more dll detach stuff here! */
372 NlsUninit();
373
374 /* Delete DLL critical section */
375 if (ConsoleInitialized == TRUE)
376 {
377 ConsoleInitialized = FALSE;
378 RtlDeleteCriticalSection (&ConsoleLock);
379 }
380 RtlDeleteCriticalSection (&DllLock);
381
382 /* Close object base directory */
383 NtClose(hBaseDir);
384
385 RtlFreeUnicodeString (&SystemDirectory);
386 RtlFreeUnicodeString (&WindowsDirectory);
387 }
388 break;
389
390 default:
391 break;
392 }
393
394 return TRUE;
395 }
396
397 LONG
398 WINAPI
399 InterlockedIncrement(IN OUT LONG volatile *lpAddend)
400 {
401 return _InterlockedIncrement(lpAddend);
402 }
403
404 LONG
405 WINAPI
406 InterlockedDecrement(IN OUT LONG volatile *lpAddend)
407 {
408 return _InterlockedDecrement(lpAddend);
409 }
410
411 LONG
412 WINAPI
413 InterlockedExchange(IN OUT LONG volatile *Target,
414 IN LONG Value)
415 {
416 return _InterlockedExchange(Target, Value);
417 }
418
419 LONG
420 WINAPI
421 InterlockedExchangeAdd(IN OUT LONG volatile *Addend,
422 IN LONG Value)
423 {
424 return _InterlockedExchangeAdd(Addend, Value);
425 }
426
427 LONG
428 WINAPI
429 InterlockedCompareExchange(IN OUT LONG volatile *Destination,
430 IN LONG Exchange,
431 IN LONG Comperand)
432 {
433 return _InterlockedCompareExchange(Destination, Exchange, Comperand);
434 }
435
436 /* EOF */