1 /* $Id: dllmain.c 56414 2012-04-25 10:17:29Z tfaber $
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 PBASE_STATIC_SERVER_DATA BaseStaticServerData
;
24 BOOLEAN BaseRunningInServerProcess
;
26 WCHAR BaseDefaultPathBuffer
[6140];
28 HANDLE BaseNamedObjectDirectory
;
29 HMODULE hCurrentModule
= NULL
;
30 HMODULE kernel32_handle
= NULL
;
33 BOOL ConsoleInitialized
= FALSE
;
34 static BOOL DllInitialized
= FALSE
;
41 /* Critical section for various kernel32 data structures */
42 RTL_CRITICAL_SECTION BaseDllDirectoryLock
;
43 RTL_CRITICAL_SECTION ConsoleLock
;
45 extern BOOL WINAPI
DefaultConsoleCtrlHandler(DWORD Event
);
46 extern __declspec(noreturn
) VOID CALLBACK
ConsoleControlDispatcher(DWORD CodeAndFlag
);
47 extern PHANDLER_ROUTINE InitialHandler
[1];
48 extern PHANDLER_ROUTINE
* CtrlHandlers
;
49 extern ULONG NrCtrlHandlers
;
50 extern ULONG NrAllocatedHandlers
;
51 extern BOOL FASTCALL
NlsInit(VOID
);
52 extern VOID FASTCALL
NlsUninit(VOID
);
53 BOOLEAN InWindows
= FALSE
;
55 #define WIN_OBJ_DIR L"\\Windows"
56 #define SESSION_DIR L"\\Sessions"
58 /* FUNCTIONS *****************************************************************/
62 BasepInitConsole(VOID
)
64 CSR_API_MESSAGE Request
;
66 BOOLEAN NotConsole
= FALSE
;
67 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
70 WCHAR SessionDir
[256];
71 ULONG SessionId
= NtCurrentPeb()->SessionId
;
74 WCHAR lpTest
[MAX_PATH
];
75 GetModuleFileNameW(NULL
, lpTest
, MAX_PATH
);
76 DPRINT("BasepInitConsole for : %S\n", lpTest
);
77 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
78 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
79 Parameters
->StandardOutput
, Parameters
->StandardError
);
81 /* We have nothing to do if this isn't a console app... */
82 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
83 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
85 DPRINT("Image is not a console application\n");
86 Parameters
->ConsoleHandle
= NULL
;
87 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
91 /* Assume one is needed */
93 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= TRUE
;
94 Request
.Data
.AllocConsoleRequest
.ShowCmd
= si
.wShowWindow
;
96 /* Handle the special flags given to us by BasepInitializeEnvironment */
97 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
99 /* No console to create */
100 DPRINT("No console to create\n");
101 Parameters
->ConsoleHandle
= NULL
;
102 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
104 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
106 /* We'll get the real one soon */
107 DPRINT("Creating new console\n");
108 Parameters
->ConsoleHandle
= NULL
;
110 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
112 /* We'll get the real one soon */
113 DPRINT("Creating new invisible console\n");
114 Parameters
->ConsoleHandle
= NULL
;
115 Request
.Data
.AllocConsoleRequest
.ShowCmd
= SW_HIDE
;
119 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
121 Parameters
->ConsoleHandle
= 0;
123 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
127 /* Initialize Console Ctrl Handler and input EXE name */
128 ConsoleInitialized
= TRUE
;
129 RtlInitializeCriticalSection(&ConsoleLock
);
130 NrAllocatedHandlers
= 1;
132 CtrlHandlers
= InitialHandler
;
133 CtrlHandlers
[0] = DefaultConsoleCtrlHandler
;
135 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
137 SetConsoleInputExeNameW(ExeName
+ 1);
139 /* Now use the proper console handle */
140 Request
.Data
.AllocConsoleRequest
.Console
= Parameters
->ConsoleHandle
;
142 /* Setup the right Object Directory path */
145 /* Use the raw path */
146 wcscpy(SessionDir
, WIN_OBJ_DIR
);
150 /* Use the session path */
158 /* Connect to the base server */
159 DPRINT("Connecting to CSR...\n");
160 Status
= CsrClientConnectToServer(SessionDir
,
165 if (!NT_SUCCESS(Status
))
167 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status
);
171 /* Nothing to do for server-to-server */
172 if (InServer
) return TRUE
;
175 * Normally, we should be connecting to the Console CSR Server...
176 * but we don't have one yet, so we will instead simply send a create
177 * console message to the Base Server. When we finally have a Console
178 * Server, this code should be changed to send connection data instead.
180 Request
.Data
.AllocConsoleRequest
.CtrlDispatcher
= ConsoleControlDispatcher
;
181 Status
= CsrClientCallServer(&Request
,
183 CSR_CREATE_API_NUMBER(CSR_CONSOLE
, ALLOC_CONSOLE
),
184 sizeof(CSR_API_MESSAGE
));
185 if(!NT_SUCCESS(Status
) || !NT_SUCCESS(Status
= Request
.Status
))
187 DPRINT1("CSR Failed to give us a console\n");
188 /* We're lying here, so at least the process can load... */
192 /* Nothing to do if not a console app */
193 if (NotConsole
) return TRUE
;
195 /* We got the handles, let's set them */
196 if ((Parameters
->ConsoleHandle
= Request
.Data
.AllocConsoleRequest
.Console
))
198 /* If we already had some, don't use the new ones */
199 if (!Parameters
->StandardInput
)
201 Parameters
->StandardInput
= Request
.Data
.AllocConsoleRequest
.InputHandle
;
203 if (!Parameters
->StandardOutput
)
205 Parameters
->StandardOutput
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
207 if (!Parameters
->StandardError
)
209 Parameters
->StandardError
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
213 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
214 Parameters
->ConsoleHandle
,
215 Parameters
->StandardInput
,
216 Parameters
->StandardOutput
,
217 Parameters
->StandardError
);
223 BaseCreateThreadPoolThread(IN PTHREAD_START_ROUTINE Function
,
225 OUT PHANDLE ThreadHandle
)
229 /* Create a Win32 thread */
230 *ThreadHandle
= CreateRemoteThread(NtCurrentProcess(),
237 if (!(*ThreadHandle
))
239 /* Get the status value if we couldn't get a handle */
240 Status
= NtCurrentTeb()->LastStatusValue
;
241 if (NT_SUCCESS(Status
)) Status
= STATUS_UNSUCCESSFUL
;
245 /* Set success code */
246 Status
= STATUS_SUCCESS
;
255 BaseExitThreadPoolThread(IN NTSTATUS ExitStatus
)
257 /* Exit the thread */
258 ExitThread(ExitStatus
);
269 ULONG DummySize
= sizeof(Dummy
);
270 WCHAR SessionDir
[256];
272 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
275 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
277 /* Cache the PEB and Session ID */
278 Peb
= NtCurrentPeb();
279 SessionId
= Peb
->SessionId
;
283 case DLL_PROCESS_ATTACH
:
285 /* Set no filter intially */
286 GlobalTopLevelExceptionFilter
= RtlEncodePointer(NULL
);
288 /* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
289 RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread
, BaseExitThreadPoolThread
);
291 /* Don't bother us for each thread */
292 LdrDisableThreadCalloutsForDll((PVOID
)hDll
);
294 /* Initialize default path to NULL */
295 RtlInitUnicodeString(&BaseDefaultPath
, NULL
);
297 /* Setup the right Object Directory path */
300 /* Use the raw path */
301 wcscpy(SessionDir
, WIN_OBJ_DIR
);
305 /* Use the session path */
313 /* Connect to the base server */
314 DPRINT("Connecting to CSR...\n");
315 Status
= CsrClientConnectToServer(SessionDir
,
319 &BaseRunningInServerProcess
);
320 if (!NT_SUCCESS(Status
))
322 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status
);
323 NtTerminateProcess(NtCurrentProcess(), Status
);
327 /* Get the server data */
328 ASSERT(Peb
->ReadOnlyStaticServerData
);
329 BaseStaticServerData
= Peb
->ReadOnlyStaticServerData
[CSR_CONSOLE
];
330 ASSERT(BaseStaticServerData
);
332 /* Check if we are running a CSR Server */
333 if (!BaseRunningInServerProcess
)
335 /* Set the termination port for the thread */
336 DPRINT("Creating new thread for CSR\n");
340 /* Initialize heap handle table */
341 BaseDllInitializeMemoryManager();
343 /* Set HMODULE for our DLL */
344 kernel32_handle
= hCurrentModule
= hDll
;
346 /* Set the directories */
347 BaseWindowsDirectory
= BaseStaticServerData
->WindowsDirectory
;
348 BaseWindowsSystemDirectory
= BaseStaticServerData
->WindowsSystemDirectory
;
350 /* Construct the default path (using the static buffer) */
351 _snwprintf(BaseDefaultPathBuffer
, sizeof(BaseDefaultPathBuffer
) / sizeof(WCHAR
),
352 L
".;%wZ;%wZ\\system;%wZ;", &BaseWindowsSystemDirectory
, &BaseWindowsDirectory
, &BaseWindowsDirectory
);
354 BaseDefaultPath
.Buffer
= BaseDefaultPathBuffer
;
355 BaseDefaultPath
.Length
= wcslen(BaseDefaultPathBuffer
) * sizeof(WCHAR
);
356 BaseDefaultPath
.MaximumLength
= sizeof(BaseDefaultPathBuffer
);
358 /* Use remaining part of the default path buffer for the append path */
359 BaseDefaultPathAppend
.Buffer
= (PWSTR
)((ULONG_PTR
)BaseDefaultPathBuffer
+ BaseDefaultPath
.Length
);
360 BaseDefaultPathAppend
.Length
= 0;
361 BaseDefaultPathAppend
.MaximumLength
= BaseDefaultPath
.MaximumLength
- BaseDefaultPath
.Length
;
363 /* Initialize command line */
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 /* Initialize application certification globals */
384 InitializeListHead(&BasepAppCertDllsList
);
385 RtlInitializeCriticalSection(&gcsAppCert
);
387 /* Insert more dll attach stuff here! */
388 DllInitialized
= TRUE
;
389 DPRINT("Initialization complete\n");
392 case DLL_PROCESS_DETACH
:
394 DPRINT("DLL_PROCESS_DETACH\n");
395 if (DllInitialized
== TRUE
)
397 /* Insert more dll detach stuff here! */
400 /* Delete DLL critical section */
401 if (ConsoleInitialized
== TRUE
)
403 ConsoleInitialized
= FALSE
;
404 RtlDeleteCriticalSection (&ConsoleLock
);
406 RtlDeleteCriticalSection (&BaseDllDirectoryLock
);