2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/dllmain.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Ariadne (ariadne@xs4all.nl)
7 * Aleksey Bragin (aleksey@reactos.org)
12 /* INCLUDES ******************************************************************/
19 /* GLOBALS *******************************************************************/
21 PBASE_STATIC_SERVER_DATA BaseStaticServerData
;
23 BOOLEAN BaseRunningInServerProcess
;
25 WCHAR BaseDefaultPathBuffer
[6140];
27 HANDLE BaseNamedObjectDirectory
;
28 HMODULE hCurrentModule
= NULL
;
29 HMODULE kernel32_handle
= NULL
;
32 BOOL ConsoleInitialized
= FALSE
;
33 static BOOL DllInitialized
= FALSE
;
35 /* Critical section for various kernel32 data structures */
36 RTL_CRITICAL_SECTION BaseDllDirectoryLock
;
37 RTL_CRITICAL_SECTION ConsoleLock
;
39 extern DWORD WINAPI
ConsoleControlDispatcher(IN LPVOID lpThreadParameter
);
40 extern HANDLE InputWaitHandle
;
42 extern BOOL FASTCALL
NlsInit(VOID
);
43 extern VOID FASTCALL
NlsUninit(VOID
);
45 #define WIN_OBJ_DIR L"\\Windows"
46 #define SESSION_DIR L"\\Sessions"
48 /* FUNCTIONS *****************************************************************/
52 BasepInitConsole(VOID
)
55 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
58 WCHAR SessionDir
[256];
59 ULONG SessionId
= NtCurrentPeb()->SessionId
;
62 CONSOLE_CONNECTION_INFO ConnectInfo
;
63 ULONG ConnectInfoSize
= sizeof(ConnectInfo
);
65 WCHAR lpTest
[MAX_PATH
];
66 GetModuleFileNameW(NULL
, lpTest
, MAX_PATH
);
67 DPRINT("BasepInitConsole for : %S\n", lpTest
);
68 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
69 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
70 Parameters
->StandardOutput
, Parameters
->StandardError
);
72 /* Initialize our global console DLL lock */
73 Status
= RtlInitializeCriticalSection(&ConsoleLock
);
74 if (!NT_SUCCESS(Status
)) return FALSE
;
75 ConsoleInitialized
= TRUE
;
77 /* We have nothing to do if this isn't a console app... */
78 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
79 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
81 DPRINT("Image is not a console application\n");
82 Parameters
->ConsoleHandle
= NULL
;
83 ConnectInfo
.ConsoleNeeded
= FALSE
; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
87 /* Assume one is needed */
89 ConnectInfo
.ConsoleNeeded
= TRUE
;
90 ConnectInfo
.ShowCmd
= si
.wShowWindow
;
92 /* Handle the special flags given to us by BasePushProcessParameters */
93 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
95 /* No console to create */
96 DPRINT("No console to create\n");
97 Parameters
->ConsoleHandle
= NULL
;
98 ConnectInfo
.ConsoleNeeded
= FALSE
;
100 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
102 /* We'll get the real one soon */
103 DPRINT("Creating new console\n");
104 Parameters
->ConsoleHandle
= NULL
;
106 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
108 /* We'll get the real one soon */
109 DPRINT("Creating new invisible console\n");
110 Parameters
->ConsoleHandle
= NULL
;
111 ConnectInfo
.ShowCmd
= SW_HIDE
;
115 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
117 Parameters
->ConsoleHandle
= NULL
;
119 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
123 /* Now use the proper console handle */
124 ConnectInfo
.Console
= Parameters
->ConsoleHandle
;
126 /* Initialize Console Ctrl Handler and input EXE name */
127 InitConsoleCtrlHandling();
128 ConnectInfo
.CtrlDispatcher
= ConsoleControlDispatcher
;
130 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
132 SetConsoleInputExeNameW(ExeName
+ 1);
134 /* Setup the right Object Directory path */
137 /* Use the raw path */
138 wcscpy(SessionDir
, WIN_OBJ_DIR
);
142 /* Use the session path */
150 /* Connect to the Console Server */
151 DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
152 Status
= CsrClientConnectToServer(SessionDir
,
153 CONSRV_SERVERDLL_INDEX
,
157 if (!NT_SUCCESS(Status
))
159 DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status
);
163 /* Nothing to do for server-to-server */
164 if (InServer
) return TRUE
;
166 /* Nothing to do if not a console app */
167 if (!ConnectInfo
.ConsoleNeeded
) return TRUE
;
169 /* We got the handles, let's set them */
170 if ((Parameters
->ConsoleHandle
= ConnectInfo
.Console
))
172 /* If we already had some, don't use the new ones */
173 if (!Parameters
->StandardInput
)
175 Parameters
->StandardInput
= ConnectInfo
.InputHandle
;
177 if (!Parameters
->StandardOutput
)
179 Parameters
->StandardOutput
= ConnectInfo
.OutputHandle
;
181 if (!Parameters
->StandardError
)
183 Parameters
->StandardError
= ConnectInfo
.ErrorHandle
;
187 InputWaitHandle
= ConnectInfo
.InputWaitHandle
;
189 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
190 Parameters
->ConsoleHandle
,
191 Parameters
->StandardInput
,
192 Parameters
->StandardOutput
,
193 Parameters
->StandardError
);
199 BaseCreateThreadPoolThread(IN PTHREAD_START_ROUTINE Function
,
201 OUT PHANDLE ThreadHandle
)
205 /* Create a Win32 thread */
206 *ThreadHandle
= CreateRemoteThread(NtCurrentProcess(),
213 if (!(*ThreadHandle
))
215 /* Get the status value if we couldn't get a handle */
216 Status
= NtCurrentTeb()->LastStatusValue
;
217 if (NT_SUCCESS(Status
)) Status
= STATUS_UNSUCCESSFUL
;
221 /* Set success code */
222 Status
= STATUS_SUCCESS
;
231 BaseExitThreadPoolThread(IN NTSTATUS ExitStatus
)
233 /* Exit the thread */
234 ExitThread(ExitStatus
);
245 ULONG DummySize
= sizeof(Dummy
);
246 WCHAR SessionDir
[256];
248 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
251 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
253 /* Cache the PEB and Session ID */
254 Peb
= NtCurrentPeb();
255 SessionId
= Peb
->SessionId
;
259 case DLL_PROCESS_ATTACH
:
261 /* Set no filter intially */
262 GlobalTopLevelExceptionFilter
= RtlEncodePointer(NULL
);
264 /* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
265 RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread
, BaseExitThreadPoolThread
);
267 /* Don't bother us for each thread */
268 LdrDisableThreadCalloutsForDll((PVOID
)hDll
);
270 /* Initialize default path to NULL */
271 RtlInitUnicodeString(&BaseDefaultPath
, NULL
);
273 /* Setup the right Object Directory path */
276 /* Use the raw path */
277 wcscpy(SessionDir
, WIN_OBJ_DIR
);
281 /* Use the session path */
289 /* Connect to the base server */
290 DPRINT("Connecting to CSR in DllMain...\n");
291 Status
= CsrClientConnectToServer(SessionDir
,
292 BASESRV_SERVERDLL_INDEX
,
295 &BaseRunningInServerProcess
);
296 if (!NT_SUCCESS(Status
))
298 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status
);
299 NtTerminateProcess(NtCurrentProcess(), Status
);
302 DPRINT("kernel32 DllMain - OK, connection succeeded\n");
304 /* Get the server data */
305 ASSERT(Peb
->ReadOnlyStaticServerData
);
306 BaseStaticServerData
= Peb
->ReadOnlyStaticServerData
[BASESRV_SERVERDLL_INDEX
];
307 ASSERT(BaseStaticServerData
);
309 /* Check if we are running a CSR Server */
310 if (!BaseRunningInServerProcess
)
312 /* Set the termination port for the thread */
313 DPRINT("Creating new thread for CSR\n");
317 /* Initialize heap handle table */
318 BaseDllInitializeMemoryManager();
320 /* Set HMODULE for our DLL */
321 kernel32_handle
= hCurrentModule
= hDll
;
323 /* Set the directories */
324 BaseWindowsDirectory
= BaseStaticServerData
->WindowsDirectory
;
325 BaseWindowsSystemDirectory
= BaseStaticServerData
->WindowsSystemDirectory
;
327 /* Construct the default path (using the static buffer) */
328 _snwprintf(BaseDefaultPathBuffer
, sizeof(BaseDefaultPathBuffer
) / sizeof(WCHAR
),
329 L
".;%wZ;%wZ\\system;%wZ;", &BaseWindowsSystemDirectory
, &BaseWindowsDirectory
, &BaseWindowsDirectory
);
331 BaseDefaultPath
.Buffer
= BaseDefaultPathBuffer
;
332 BaseDefaultPath
.Length
= wcslen(BaseDefaultPathBuffer
) * sizeof(WCHAR
);
333 BaseDefaultPath
.MaximumLength
= sizeof(BaseDefaultPathBuffer
);
335 /* Use remaining part of the default path buffer for the append path */
336 BaseDefaultPathAppend
.Buffer
= (PWSTR
)((ULONG_PTR
)BaseDefaultPathBuffer
+ BaseDefaultPath
.Length
);
337 BaseDefaultPathAppend
.Length
= 0;
338 BaseDefaultPathAppend
.MaximumLength
= BaseDefaultPath
.MaximumLength
- BaseDefaultPath
.Length
;
340 /* Initialize command line */
343 /* Initialize the DLL critical section */
344 RtlInitializeCriticalSection(&BaseDllDirectoryLock
);
346 /* Initialize the National Language Support routines */
349 DPRINT1("NLS Init failed\n");
353 /* Initialize Console Support */
354 if (!BasepInitConsole())
356 DPRINT1("Failure to set up console\n");
360 /* Initialize application certification globals */
361 InitializeListHead(&BasepAppCertDllsList
);
362 RtlInitializeCriticalSection(&gcsAppCert
);
364 /* Insert more dll attach stuff here! */
365 DllInitialized
= TRUE
;
366 DPRINT("Initialization complete\n");
369 case DLL_PROCESS_DETACH
:
371 DPRINT("DLL_PROCESS_DETACH\n");
372 if (DllInitialized
== TRUE
)
374 /* Insert more dll detach stuff here! */
377 /* Delete DLL critical section */
378 if (ConsoleInitialized
== TRUE
)
380 ConsoleInitialized
= FALSE
;
381 RtlDeleteCriticalSection(&ConsoleLock
);
383 RtlDeleteCriticalSection(&BaseDllDirectoryLock
);