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)
12 /* INCLUDES ******************************************************************/
19 /* GLOBALS *******************************************************************/
21 extern UNICODE_STRING SystemDirectory
;
22 extern UNICODE_STRING WindowsDirectory
;
24 HANDLE hProcessHeap
= NULL
;
25 HMODULE hCurrentModule
= NULL
;
26 HANDLE hBaseDir
= NULL
;
29 BOOL ConsoleInitialized
= FALSE
;
31 static BOOL DllInitialized
= FALSE
;
38 /* Critical section for various kernel32 data structures */
39 RTL_CRITICAL_SECTION DllLock
;
40 RTL_CRITICAL_SECTION ConsoleLock
;
42 extern BOOL WINAPI
DefaultConsoleCtrlHandler(DWORD Event
);
43 extern __declspec(noreturn
) VOID CALLBACK
ConsoleControlDispatcher(DWORD CodeAndFlag
);
44 extern PHANDLER_ROUTINE InitialHandler
[1];
45 extern PHANDLER_ROUTINE
* CtrlHandlers
;
46 extern ULONG NrCtrlHandlers
;
47 extern ULONG NrAllocatedHandlers
;
48 extern BOOL FASTCALL
NlsInit(VOID
);
49 extern VOID FASTCALL
NlsUninit(VOID
);
50 BOOLEAN InWindows
= FALSE
;
54 DuplicateConsoleHandle(HANDLE hConsole
,
55 DWORD dwDesiredAccess
,
59 #define WIN_OBJ_DIR L"\\Windows"
60 #define SESSION_DIR L"\\Sessions"
62 SYSTEM_BASIC_INFORMATION BaseCachedSysInfo
;
64 /* FUNCTIONS *****************************************************************/
68 OpenBaseDirectory(PHANDLE DirHandle
)
70 OBJECT_ATTRIBUTES ObjectAttributes
;
71 UNICODE_STRING Name
= RTL_CONSTANT_STRING(L
"\\BaseNamedObjects");
74 InitializeObjectAttributes(&ObjectAttributes
,
80 Status
= NtOpenDirectoryObject(DirHandle
,
81 DIRECTORY_ALL_ACCESS
&
82 ~(DELETE
| WRITE_DAC
| WRITE_OWNER
),
84 if (!NT_SUCCESS(Status
))
89 DPRINT("Opened BNO: %lx\n", *DirHandle
);
98 BaseQueryModuleData(IN LPSTR ModuleName
,
104 DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n",
118 BaseProcessInitPostImport(VOID
)
120 /* FIXME: Initialize TS pointers */
121 return STATUS_SUCCESS
;
126 BasepInitConsole(VOID
)
128 CSR_API_MESSAGE Request
;
131 BOOLEAN NotConsole
= FALSE
;
132 PRTL_USER_PROCESS_PARAMETERS Parameters
= NtCurrentPeb()->ProcessParameters
;
135 WCHAR lpTest
[MAX_PATH
];
136 GetModuleFileNameW(NULL
, lpTest
, MAX_PATH
);
137 DPRINT("BasepInitConsole for : %S\n", lpTest
);
138 DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
139 Parameters
->ConsoleHandle
, Parameters
->StandardInput
,
140 Parameters
->StandardOutput
, Parameters
->StandardError
);
142 /* We have nothing to do if this isn't a console app... */
143 if (RtlImageNtHeader(GetModuleHandle(NULL
))->OptionalHeader
.Subsystem
!=
144 IMAGE_SUBSYSTEM_WINDOWS_CUI
)
146 DPRINT("Image is not a console application\n");
147 Parameters
->ConsoleHandle
= NULL
;
148 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
152 /* Assume one is needed */
153 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= TRUE
;
154 Request
.Data
.AllocConsoleRequest
.Visible
= TRUE
;
156 /* Handle the special flags given to us by BasepInitializeEnvironment */
157 if (Parameters
->ConsoleHandle
== HANDLE_DETACHED_PROCESS
)
159 /* No console to create */
160 DPRINT("No console to create\n");
161 Parameters
->ConsoleHandle
= NULL
;
162 Request
.Data
.AllocConsoleRequest
.ConsoleNeeded
= FALSE
;
164 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NEW_CONSOLE
)
166 /* We'll get the real one soon */
167 DPRINT("Creating new console\n");
168 Parameters
->ConsoleHandle
= NULL
;
170 else if (Parameters
->ConsoleHandle
== HANDLE_CREATE_NO_WINDOW
)
172 /* We'll get the real one soon */
173 DPRINT("Creating new invisible console\n");
174 Parameters
->ConsoleHandle
= NULL
;
175 Request
.Data
.AllocConsoleRequest
.Visible
= FALSE
;
179 if (Parameters
->ConsoleHandle
== INVALID_HANDLE_VALUE
)
181 Parameters
->ConsoleHandle
= 0;
183 DPRINT("Using existing console: %x\n", Parameters
->ConsoleHandle
);
187 /* Initialize Console Ctrl Handler and input EXE name */
188 ConsoleInitialized
= TRUE
;
189 RtlInitializeCriticalSection(&ConsoleLock
);
190 NrAllocatedHandlers
= 1;
192 CtrlHandlers
= InitialHandler
;
193 CtrlHandlers
[0] = DefaultConsoleCtrlHandler
;
195 ExeName
= wcsrchr(Parameters
->ImagePathName
.Buffer
, L
'\\');
197 SetConsoleInputExeNameW(ExeName
+ 1);
199 /* Now use the proper console handle */
200 Request
.Data
.AllocConsoleRequest
.Console
= Parameters
->ConsoleHandle
;
203 * Normally, we should be connecting to the Console CSR Server...
204 * but we don't have one yet, so we will instead simply send a create
205 * console message to the Base Server. When we finally have a Console
206 * Server, this code should be changed to send connection data instead.
208 CsrRequest
= MAKE_CSR_API(ALLOC_CONSOLE
, CSR_CONSOLE
);
209 Request
.Data
.AllocConsoleRequest
.CtrlDispatcher
= ConsoleControlDispatcher
;
210 Status
= CsrClientCallServer(&Request
,
213 sizeof(CSR_API_MESSAGE
));
214 if(!NT_SUCCESS(Status
) || !NT_SUCCESS(Status
= Request
.Status
))
216 DPRINT1("CSR Failed to give us a console\n");
217 /* We're lying here, so at least the process can load... */
221 if (NotConsole
) return TRUE
;
223 /* We got the handles, let's set them */
224 if ((Parameters
->ConsoleHandle
= Request
.Data
.AllocConsoleRequest
.Console
))
226 /* If we already had some, don't use the new ones */
227 if (!Parameters
->StandardInput
)
229 Parameters
->StandardInput
= Request
.Data
.AllocConsoleRequest
.InputHandle
;
231 if (!Parameters
->StandardOutput
)
233 Parameters
->StandardOutput
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
235 if (!Parameters
->StandardError
)
237 Parameters
->StandardError
= Request
.Data
.AllocConsoleRequest
.OutputHandle
;
241 DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
242 Parameters
->ConsoleHandle
,
243 Parameters
->StandardInput
,
244 Parameters
->StandardOutput
,
245 Parameters
->StandardError
);
259 ULONG DummySize
= sizeof(Dummy
);
260 WCHAR SessionDir
[256];
262 DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
265 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
267 /* Cache the PEB and Session ID */
268 Peb
= NtCurrentPeb();
269 SessionId
= Peb
->SessionId
;
273 case DLL_PROCESS_ATTACH
:
275 /* Don't bother us for each thread */
276 LdrDisableThreadCalloutsForDll((PVOID
)hDll
);
278 /* Setup the right Object Directory path */
281 /* Use the raw path */
282 wcscpy(SessionDir
, WIN_OBJ_DIR
);
286 /* Use the session path */
294 /* Connect to the base server */
295 DPRINT("Connecting to CSR...\n");
296 Status
= CsrClientConnectToServer(SessionDir
,
301 if (!NT_SUCCESS(Status
))
303 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status
);
304 ZwTerminateProcess(NtCurrentProcess(), Status
);
308 /* Check if we are running a CSR Server */
311 /* Set the termination port for the thread */
312 DPRINT("Creating new thread for CSR\n");
316 hProcessHeap
= RtlGetProcessHeap();
317 RtlInitializeHandleTable(0xFFFF,
318 sizeof(BASE_HEAP_HANDLE_ENTRY
),
319 &BaseHeapHandleTable
);
320 hCurrentModule
= hDll
;
321 DPRINT("Heap: %p\n", hProcessHeap
);
324 * Initialize WindowsDirectory and SystemDirectory
326 DPRINT("NtSystemRoot: %S\n", SharedUserData
->NtSystemRoot
);
327 RtlCreateUnicodeString (&WindowsDirectory
, SharedUserData
->NtSystemRoot
);
328 SystemDirectory
.MaximumLength
= WindowsDirectory
.MaximumLength
+ 18;
329 SystemDirectory
.Length
= WindowsDirectory
.Length
+ 18;
330 SystemDirectory
.Buffer
= RtlAllocateHeap(hProcessHeap
,
332 SystemDirectory
.MaximumLength
);
333 if(SystemDirectory
.Buffer
== NULL
)
337 wcscpy(SystemDirectory
.Buffer
, WindowsDirectory
.Buffer
);
338 wcscat(SystemDirectory
.Buffer
, L
"\\System32");
340 /* Initialize command line */
343 /* Open object base directory */
344 Status
= OpenBaseDirectory(&hBaseDir
);
345 if (!NT_SUCCESS(Status
))
347 DPRINT1("Failed to open object base directory (Status %lx)\n", Status
);
351 /* Initialize the DLL critical section */
352 RtlInitializeCriticalSection(&DllLock
);
354 /* Initialize the National Language Support routines */
357 DPRINT1("NLS Init failed\n");
361 /* Initialize Console Support */
362 if (!BasepInitConsole())
364 DPRINT1("Failure to set up console\n");
368 /* Cache static system information */
369 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
371 sizeof(BaseCachedSysInfo
),
373 if (!NT_SUCCESS(Status
))
375 DPRINT1("Failure to get system information\n");
379 /* Insert more dll attach stuff here! */
380 DllInitialized
= TRUE
;
381 DPRINT("Initialization complete\n");
384 case DLL_PROCESS_DETACH
:
386 DPRINT("DLL_PROCESS_DETACH\n");
387 if (DllInitialized
== TRUE
)
389 /* Insert more dll detach stuff here! */
392 /* Delete DLL critical section */
393 if (ConsoleInitialized
== TRUE
)
395 ConsoleInitialized
= FALSE
;
396 RtlDeleteCriticalSection (&ConsoleLock
);
398 RtlDeleteCriticalSection (&DllLock
);
400 /* Close object base directory */
403 RtlFreeUnicodeString (&SystemDirectory
);
404 RtlFreeUnicodeString (&WindowsDirectory
);
415 #undef InterlockedIncrement
416 #undef InterlockedDecrement
417 #undef InterlockedExchange
418 #undef InterlockedExchangeAdd
419 #undef InterlockedCompareExchange
423 InterlockedIncrement(IN OUT LONG
volatile *lpAddend
)
425 return _InterlockedIncrement(lpAddend
);
430 InterlockedDecrement(IN OUT LONG
volatile *lpAddend
)
432 return _InterlockedDecrement(lpAddend
);
435 #undef InterlockedExchange
438 InterlockedExchange(IN OUT LONG
volatile *Target
,
441 return _InterlockedExchange(Target
, Value
);
446 InterlockedExchangeAdd(IN OUT LONG
volatile *Addend
,
449 return _InterlockedExchangeAdd(Addend
, Value
);
454 InterlockedCompareExchange(IN OUT LONG
volatile *Destination
,
458 return _InterlockedCompareExchange(Destination
, Exchange
, Comperand
);