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 * Aleksey Bragin (aleksey@reactos.org)
13 /* INCLUDES ******************************************************************/
20 /* GLOBALS *******************************************************************/
22 extern UNICODE_STRING SystemDirectory
;
23 extern UNICODE_STRING WindowsDirectory
;
25 PBASE_STATIC_SERVER_DATA BaseStaticServerData
;
27 BOOLEAN BaseRunningInServerProcess
;
29 WCHAR BaseDefaultPathBuffer
[6140];
31 HANDLE BaseNamedObjectDirectory
;
32 HANDLE hProcessHeap
= NULL
;
33 HMODULE hCurrentModule
= NULL
;
34 HMODULE kernel32_handle
= NULL
;
35 HANDLE hBaseDir
= NULL
;
38 BOOL ConsoleInitialized
= FALSE
;
39 UNICODE_STRING BaseWindowsDirectory
, BaseWindowsSystemDirectory
;
40 static BOOL DllInitialized
= FALSE
;
47 /* Critical section for various kernel32 data structures */
48 RTL_CRITICAL_SECTION BaseDllDirectoryLock
;
49 RTL_CRITICAL_SECTION ConsoleLock
;
51 extern BOOL WINAPI
DefaultConsoleCtrlHandler(DWORD Event
);
52 extern __declspec(noreturn
) VOID CALLBACK
ConsoleControlDispatcher(DWORD CodeAndFlag
);
53 extern PHANDLER_ROUTINE InitialHandler
[1];
54 extern PHANDLER_ROUTINE
* CtrlHandlers
;
55 extern ULONG NrCtrlHandlers
;
56 extern ULONG NrAllocatedHandlers
;
57 extern BOOL FASTCALL
NlsInit(VOID
);
58 extern VOID FASTCALL
NlsUninit(VOID
);
59 BOOLEAN InWindows
= FALSE
;
63 DuplicateConsoleHandle(HANDLE hConsole
,
64 DWORD dwDesiredAccess
,
68 #define WIN_OBJ_DIR L"\\Windows"
69 #define SESSION_DIR L"\\Sessions"
71 /* FUNCTIONS *****************************************************************/
75 BaseGetNamedObjectDirectory(VOID
)
77 OBJECT_ATTRIBUTES ObjectAttributes
;
80 InitializeObjectAttributes(&ObjectAttributes
,
81 &BaseStaticServerData
->NamedObjectDirectory
,
86 Status
= NtOpenDirectoryObject(&BaseNamedObjectDirectory
,
87 DIRECTORY_ALL_ACCESS
&
88 ~(DELETE
| WRITE_DAC
| WRITE_OWNER
),
90 if (!NT_SUCCESS(Status
)) return Status
;
92 DPRINT("Opened BNO: %lx\n", BaseNamedObjectDirectory
);
101 BaseQueryModuleData(IN LPSTR ModuleName
,
107 DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n",
121 BaseProcessInitPostImport(VOID
)
123 /* FIXME: Initialize TS pointers */
124 return STATUS_SUCCESS
;
129 BasepInitConsole(VOID
)
131 CSR_API_MESSAGE Request
;
134 BOOLEAN NotConsole
= FALSE
;
135 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
138 WCHAR lpTest
[MAX_PATH
];
139 GetModuleFileNameW(NULL
, lpTest
, MAX_PATH
);
140 DPRINT("BasepInitConsole for : %S\n", lpTest
);
141 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
142 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
143 Parameters
->StandardOutput
, Parameters
->StandardError
);
145 /* We have nothing to do if this isn't a console app... */
146 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
147 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
149 DPRINT("Image is not a console application\n");
150 Parameters
->ConsoleHandle
= NULL
;
151 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
155 /* Assume one is needed */
156 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= TRUE
;
157 Request
.Data
.AllocConsoleRequest
.Visible
= TRUE
;
159 /* Handle the special flags given to us by BasepInitializeEnvironment */
160 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
162 /* No console to create */
163 DPRINT("No console to create\n");
164 Parameters
->ConsoleHandle
= NULL
;
165 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
167 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
169 /* We'll get the real one soon */
170 DPRINT("Creating new console\n");
171 Parameters
->ConsoleHandle
= NULL
;
173 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
175 /* We'll get the real one soon */
176 DPRINT("Creating new invisible console\n");
177 Parameters
->ConsoleHandle
= NULL
;
178 Request
.Data
.AllocConsoleRequest
.Visible
= FALSE
;
182 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
184 Parameters
->ConsoleHandle
= 0;
186 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
190 /* Initialize Console Ctrl Handler and input EXE name */
191 ConsoleInitialized
= TRUE
;
192 RtlInitializeCriticalSection(&ConsoleLock
);
193 NrAllocatedHandlers
= 1;
195 CtrlHandlers
= InitialHandler
;
196 CtrlHandlers
[0] = DefaultConsoleCtrlHandler
;
198 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
200 SetConsoleInputExeNameW(ExeName
+ 1);
202 /* Now use the proper console handle */
203 Request
.Data
.AllocConsoleRequest
.Console
= Parameters
->ConsoleHandle
;
206 * Normally, we should be connecting to the Console CSR Server...
207 * but we don't have one yet, so we will instead simply send a create
208 * console message to the Base Server. When we finally have a Console
209 * Server, this code should be changed to send connection data instead.
211 CsrRequest
= MAKE_CSR_API(ALLOC_CONSOLE
, CSR_CONSOLE
);
212 Request
.Data
.AllocConsoleRequest
.CtrlDispatcher
= ConsoleControlDispatcher
;
213 Status
= CsrClientCallServer(&Request
,
216 sizeof(CSR_API_MESSAGE
));
217 if(!NT_SUCCESS(Status
) || !NT_SUCCESS(Status
= Request
.Status
))
219 DPRINT1("CSR Failed to give us a console\n");
220 /* We're lying here, so at least the process can load... */
224 if (NotConsole
) return TRUE
;
226 /* We got the handles, let's set them */
227 if ((Parameters
->ConsoleHandle
= Request
.Data
.AllocConsoleRequest
.Console
))
229 /* If we already had some, don't use the new ones */
230 if (!Parameters
->StandardInput
)
232 Parameters
->StandardInput
= Request
.Data
.AllocConsoleRequest
.InputHandle
;
234 if (!Parameters
->StandardOutput
)
236 Parameters
->StandardOutput
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
238 if (!Parameters
->StandardError
)
240 Parameters
->StandardError
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
244 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
245 Parameters
->ConsoleHandle
,
246 Parameters
->StandardInput
,
247 Parameters
->StandardOutput
,
248 Parameters
->StandardError
);
260 ULONG DummySize
= sizeof(Dummy
);
261 WCHAR SessionDir
[256];
263 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
266 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
268 /* Cache the PEB and Session ID */
269 Peb
= NtCurrentPeb();
270 SessionId
= Peb
->SessionId
;
274 case DLL_PROCESS_ATTACH
:
276 /* Don't bother us for each thread */
277 LdrDisableThreadCalloutsForDll((PVOID
)hDll
);
279 /* Initialize default path to NULL */
280 RtlInitUnicodeString(&BaseDefaultPath
, NULL
);
282 /* Setup the right Object Directory path */
285 /* Use the raw path */
286 wcscpy(SessionDir
, WIN_OBJ_DIR
);
290 /* Use the session path */
298 /* Connect to the base server */
299 DPRINT("Connecting to CSR...\n");
300 Status
= CsrClientConnectToServer(SessionDir
,
304 &BaseRunningInServerProcess
);
305 if (!NT_SUCCESS(Status
))
307 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status
);
308 ZwTerminateProcess(NtCurrentProcess(), Status
);
312 /* Get the server data */
313 ASSERT(Peb
->ReadOnlyStaticServerData
);
314 BaseStaticServerData
= Peb
->ReadOnlyStaticServerData
[CSR_CONSOLE
];
315 ASSERT(BaseStaticServerData
);
317 /* Check if we are running a CSR Server */
318 if (!BaseRunningInServerProcess
)
320 /* Set the termination port for the thread */
321 DPRINT("Creating new thread for CSR\n");
325 /* Initialize heap handle table */
326 hProcessHeap
= RtlGetProcessHeap();
327 RtlInitializeHandleTable(0xFFFF,
328 sizeof(BASE_HEAP_HANDLE_ENTRY
),
329 &BaseHeapHandleTable
);
330 DPRINT("Heap: %p\n", hProcessHeap
);
332 /* Set HMODULE for our DLL */
333 kernel32_handle
= hCurrentModule
= hDll
;
335 /* Set the directories */
336 BaseWindowsDirectory
= BaseStaticServerData
->WindowsDirectory
;
337 BaseWindowsSystemDirectory
= BaseStaticServerData
->WindowsSystemDirectory
;
338 SystemDirectory
= BaseWindowsSystemDirectory
;
339 WindowsDirectory
= BaseWindowsDirectory
;
341 /* Construct the default path (using the static buffer) */
342 _snwprintf(BaseDefaultPathBuffer
, sizeof(BaseDefaultPathBuffer
) / sizeof(WCHAR
),
343 L
".;%wZ;%wZ\\system;%wZ;", &SystemDirectory
, &WindowsDirectory
, &WindowsDirectory
);
345 BaseDefaultPath
.Buffer
= BaseDefaultPathBuffer
;
346 BaseDefaultPath
.Length
= wcslen(BaseDefaultPathBuffer
) * sizeof(WCHAR
);
347 BaseDefaultPath
.MaximumLength
= sizeof(BaseDefaultPathBuffer
);
349 /* Use remaining part of the default path buffer for the append path */
350 BaseDefaultPathAppend
.Buffer
= (PWSTR
)((ULONG_PTR
)BaseDefaultPathBuffer
+ BaseDefaultPath
.Length
);
351 BaseDefaultPathAppend
.Length
= 0;
352 BaseDefaultPathAppend
.MaximumLength
= BaseDefaultPath
.MaximumLength
- BaseDefaultPath
.Length
;
354 /* Initialize command line */
357 /* Open object base directory */
358 Status
= BaseGetNamedObjectDirectory();
359 hBaseDir
= BaseNamedObjectDirectory
;
360 if (!NT_SUCCESS(Status
))
362 DPRINT1("Failed to open object base directory (Status %lx)\n", Status
);
366 /* Initialize the DLL critical section */
367 RtlInitializeCriticalSection(&BaseDllDirectoryLock
);
369 /* Initialize the National Language Support routines */
372 DPRINT1("NLS Init failed\n");
376 /* Initialize Console Support */
377 if (!BasepInitConsole())
379 DPRINT1("Failure to set up console\n");
383 /* Insert more dll attach stuff here! */
384 DllInitialized
= TRUE
;
385 DPRINT("Initialization complete\n");
388 case DLL_PROCESS_DETACH
:
390 DPRINT("DLL_PROCESS_DETACH\n");
391 if (DllInitialized
== TRUE
)
393 /* Insert more dll detach stuff here! */
396 /* Delete DLL critical section */
397 if (ConsoleInitialized
== TRUE
)
399 ConsoleInitialized
= FALSE
;
400 RtlDeleteCriticalSection (&ConsoleLock
);
402 RtlDeleteCriticalSection (&BaseDllDirectoryLock
);
404 /* Close object base directory */
416 #undef InterlockedIncrement
417 #undef InterlockedDecrement
418 #undef InterlockedExchange
419 #undef InterlockedExchangeAdd
420 #undef InterlockedCompareExchange
424 InterlockedIncrement(IN OUT LONG
volatile *lpAddend
)
426 return _InterlockedIncrement(lpAddend
);
431 InterlockedDecrement(IN OUT LONG
volatile *lpAddend
)
433 return _InterlockedDecrement(lpAddend
);
436 #undef InterlockedExchange
439 InterlockedExchange(IN OUT LONG
volatile *Target
,
442 return _InterlockedExchange(Target
, Value
);
447 InterlockedExchangeAdd(IN OUT LONG
volatile *Addend
,
450 return _InterlockedExchangeAdd(Addend
, Value
);
455 InterlockedCompareExchange(IN OUT LONG
volatile *Destination
,
459 return _InterlockedCompareExchange(Destination
, Exchange
, Comperand
);