xref: /reactos/dll/win32/kernel32/client/dllmain.c (revision 8a978a17)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/kernel32/client/dllmain.c
5  * PURPOSE:         Initialization
6  * PROGRAMMERS:     Ariadne (ariadne@xs4all.nl)
7  *                  Aleksey Bragin (aleksey@reactos.org)
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <k32.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS *******************************************************************/
18 
19 PBASE_STATIC_SERVER_DATA BaseStaticServerData;
20 BOOLEAN BaseRunningInServerProcess = FALSE;
21 
22 WCHAR BaseDefaultPathBuffer[6140];
23 
24 HANDLE BaseNamedObjectDirectory;
25 HMODULE hCurrentModule = NULL;
26 HMODULE kernel32_handle = NULL;
27 PPEB Peb;
28 ULONG SessionId;
29 static BOOL DllInitialized = FALSE;
30 
31 /* Critical section for various kernel32 data structures */
32 RTL_CRITICAL_SECTION BaseDllDirectoryLock;
33 
34 extern BOOL FASTCALL NlsInit(VOID);
35 extern VOID FASTCALL NlsUninit(VOID);
36 
37 #define WIN_OBJ_DIR L"\\Windows"
38 #define SESSION_DIR L"\\Sessions"
39 
40 /* FUNCTIONS *****************************************************************/
41 
42 NTSTATUS
43 NTAPI
44 BaseCreateThreadPoolThread(IN PTHREAD_START_ROUTINE Function,
45                            IN PVOID Parameter,
46                            OUT PHANDLE ThreadHandle)
47 {
48     NTSTATUS Status;
49 
50     /* Create a Win32 thread */
51     *ThreadHandle = CreateRemoteThread(NtCurrentProcess(),
52                                        NULL,
53                                        0,
54                                        Function,
55                                        Parameter,
56                                        CREATE_SUSPENDED,
57                                        NULL);
58     if (!(*ThreadHandle))
59     {
60         /* Get the status value if we couldn't get a handle */
61         Status = NtCurrentTeb()->LastStatusValue;
62         if (NT_SUCCESS(Status)) Status = STATUS_UNSUCCESSFUL;
63     }
64     else
65     {
66         /* Set success code */
67         Status = STATUS_SUCCESS;
68     }
69 
70     /* All done */
71     return Status;
72 }
73 
74 NTSTATUS
75 NTAPI
76 BaseExitThreadPoolThread(IN NTSTATUS ExitStatus)
77 {
78     /* Exit the thread */
79     ExitThread(ExitStatus);
80     return STATUS_SUCCESS;
81 }
82 
83 BOOL
84 WINAPI
85 DllMain(HANDLE hDll,
86         DWORD dwReason,
87         LPVOID lpReserved)
88 {
89     NTSTATUS Status;
90     BASESRV_API_CONNECTINFO ConnectInfo;
91     ULONG ConnectInfoSize = sizeof(ConnectInfo);
92     WCHAR SessionDir[256];
93 
94     DPRINT("DllMain(hInst %p, dwReason %lu)\n",
95            hDll, dwReason);
96 
97     Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
98 
99     /* Cache the PEB and Session ID */
100     Peb = NtCurrentPeb();
101     SessionId = Peb->SessionId;
102 
103     switch (dwReason)
104     {
105         case DLL_PROCESS_ATTACH:
106         {
107             /* Set no filter initially */
108             GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
109 
110             /* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
111             RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread, BaseExitThreadPoolThread);
112 
113             /* Register the manifest prober routine */
114             LdrSetDllManifestProber(BasepProbeForDllManifest);
115 
116             /* Don't bother us for each thread */
117             LdrDisableThreadCalloutsForDll((PVOID)hDll);
118 
119             /* Initialize default path to NULL */
120             RtlInitUnicodeString(&BaseDefaultPath, NULL);
121 
122             /* Setup the Object Directory path */
123             if (!SessionId)
124             {
125                 /* Use the raw path */
126                 wcscpy(SessionDir, WIN_OBJ_DIR);
127             }
128             else
129             {
130                 /* Use the session path */
131                 swprintf(SessionDir,
132                          L"%ws\\%ld%ws",
133                          SESSION_DIR,
134                          SessionId,
135                          WIN_OBJ_DIR);
136             }
137 
138             /* Connect to the Base Server */
139             Status = CsrClientConnectToServer(SessionDir,
140                                               BASESRV_SERVERDLL_INDEX,
141                                               &ConnectInfo,
142                                               &ConnectInfoSize,
143                                               &BaseRunningInServerProcess);
144             if (!NT_SUCCESS(Status))
145             {
146                 DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
147                 NtTerminateProcess(NtCurrentProcess(), Status);
148                 return FALSE;
149             }
150 
151             /* Get the server data */
152             ASSERT(Peb->ReadOnlyStaticServerData);
153             BaseStaticServerData = Peb->ReadOnlyStaticServerData[BASESRV_SERVERDLL_INDEX];
154             ASSERT(BaseStaticServerData);
155 
156             /* Check if we are running a CSR Server */
157             if (!BaseRunningInServerProcess)
158             {
159                 /* Set the termination port for the thread */
160                 DPRINT("Creating new thread for CSR\n");
161                 CsrNewThread();
162             }
163 
164             /* Initialize heap handle table */
165             BaseDllInitializeMemoryManager();
166 
167             /* Set HMODULE for our DLL */
168             kernel32_handle = hCurrentModule = hDll;
169 
170             /* Set the directories */
171             BaseWindowsDirectory = BaseStaticServerData->WindowsDirectory;
172             BaseWindowsSystemDirectory = BaseStaticServerData->WindowsSystemDirectory;
173 
174             /* Construct the default path (using the static buffer) */
175             Status = RtlStringCbPrintfW(BaseDefaultPathBuffer,
176                                      sizeof(BaseDefaultPathBuffer),
177                                      L".;%wZ;%wZ\\system;%wZ;",
178                                      &BaseWindowsSystemDirectory,
179                                      &BaseWindowsDirectory,
180                                      &BaseWindowsDirectory);
181             if (!NT_SUCCESS(Status))
182             {
183                 DPRINT1("NLS Init failed\n");
184                 return FALSE;
185             }
186 
187             BaseDefaultPath.Buffer = BaseDefaultPathBuffer;
188             BaseDefaultPath.Length = (USHORT)wcslen(BaseDefaultPathBuffer) * sizeof(WCHAR);
189             BaseDefaultPath.MaximumLength = sizeof(BaseDefaultPathBuffer);
190 
191             /* Use remaining part of the default path buffer for the append path */
192             BaseDefaultPathAppend.Buffer = (PWSTR)((ULONG_PTR)BaseDefaultPathBuffer + BaseDefaultPath.Length);
193             BaseDefaultPathAppend.Length = 0;
194             BaseDefaultPathAppend.MaximumLength = BaseDefaultPath.MaximumLength - BaseDefaultPath.Length;
195 
196             /* Initialize command line */
197             InitCommandLines();
198 
199             /* Initialize the DLL critical section */
200             RtlInitializeCriticalSection(&BaseDllDirectoryLock);
201 
202             /* Initialize the National Language Support routines */
203             if (!NlsInit())
204             {
205                 DPRINT1("NLS Init failed\n");
206                 return FALSE;
207             }
208 
209             /* Initialize Console Support */
210             if (!ConDllInitialize(dwReason, SessionDir))
211             {
212                 DPRINT1("Failed to set up console\n");
213                 return FALSE;
214             }
215 
216             /* Initialize application certification globals */
217             InitializeListHead(&BasepAppCertDllsList);
218             RtlInitializeCriticalSection(&gcsAppCert);
219 
220             /* Insert more dll attach stuff here! */
221             DllInitialized = TRUE;
222             break;
223         }
224 
225         case DLL_PROCESS_DETACH:
226         {
227             if (DllInitialized != FALSE)
228             {
229                 /* Uninitialize console support */
230                 ConDllInitialize(dwReason, NULL);
231 
232                 /* Insert more dll detach stuff here! */
233                 NlsUninit();
234 
235                 /* Delete DLL critical section */
236                 RtlDeleteCriticalSection(&BaseDllDirectoryLock);
237             }
238             break;
239         }
240 
241         case DLL_THREAD_ATTACH:
242         {
243             /* ConDllInitialize sets the current console locale for the new thread */
244             return ConDllInitialize(dwReason, NULL);
245         }
246 
247         default:
248             break;
249     }
250 
251     return TRUE;
252 }
253 
254 /* EOF */
255