Sync with trunk r43123
[reactos.git] / reactos / dll / win32 / user32 / misc / dllmain.c
1 #include <user32.h>
2
3 #include <wine/debug.h>
4 WINE_DEFAULT_DEBUG_CHANNEL(user32);
5
6 #define KEY_LENGTH 1024
7
8 static ULONG User32TlsIndex;
9 HINSTANCE User32Instance;
10
11 PPROCESSINFO g_ppi = NULL;
12 PUSER_HANDLE_TABLE gHandleTable = NULL;
13 PUSER_HANDLE_ENTRY gHandleEntries = NULL;
14 PSERVERINFO gpsi = NULL;
15 ULONG_PTR g_ulSharedDelta;
16 BOOL gfServerProcess = FALSE;
17
18 WCHAR szAppInit[KEY_LENGTH];
19
20 PUSER32_THREAD_DATA
21 User32GetThreadData()
22 {
23 return ((PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex));
24 }
25
26
27 BOOL
28 GetDllList()
29 {
30 NTSTATUS Status;
31 OBJECT_ATTRIBUTES Attributes;
32 BOOL bRet = FALSE;
33 BOOL bLoad;
34 HANDLE hKey = NULL;
35 DWORD dwSize;
36 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = NULL;
37
38 UNICODE_STRING szKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
39 UNICODE_STRING szLoadName = RTL_CONSTANT_STRING(L"LoadAppInit_DLLs");
40 UNICODE_STRING szDllsName = RTL_CONSTANT_STRING(L"AppInit_DLLs");
41
42 InitializeObjectAttributes(&Attributes, &szKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
43 Status = NtOpenKey(&hKey, KEY_READ, &Attributes);
44 if (NT_SUCCESS(Status))
45 {
46 dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD);
47 kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
48 if (!kvpInfo)
49 goto end;
50
51 Status = NtQueryValueKey(hKey,
52 &szLoadName,
53 KeyValuePartialInformation,
54 kvpInfo,
55 dwSize,
56 &dwSize);
57 if (!NT_SUCCESS(Status))
58 goto end;
59
60 RtlMoveMemory(&bLoad,
61 kvpInfo->Data,
62 kvpInfo->DataLength);
63
64 HeapFree(GetProcessHeap(), 0, kvpInfo);
65 kvpInfo = NULL;
66
67 if (bLoad)
68 {
69 Status = NtQueryValueKey(hKey,
70 &szDllsName,
71 KeyValuePartialInformation,
72 NULL,
73 0,
74 &dwSize);
75 if (Status != STATUS_BUFFER_TOO_SMALL)
76 goto end;
77
78 kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
79 if (!kvpInfo)
80 goto end;
81
82 Status = NtQueryValueKey(hKey,
83 &szDllsName,
84 KeyValuePartialInformation,
85 kvpInfo,
86 dwSize,
87 &dwSize);
88 if (NT_SUCCESS(Status))
89 {
90 LPWSTR lpBuffer = (LPWSTR)kvpInfo->Data;
91 if (*lpBuffer != UNICODE_NULL)
92 {
93 INT bytesToCopy, nullPos;
94
95 bytesToCopy = min(kvpInfo->DataLength, KEY_LENGTH * sizeof(WCHAR));
96
97 if (bytesToCopy != 0)
98 {
99 RtlMoveMemory(szAppInit,
100 kvpInfo->Data,
101 bytesToCopy);
102
103 nullPos = (bytesToCopy / sizeof(WCHAR)) - 1;
104
105 /* ensure string is terminated */
106 szAppInit[nullPos] = UNICODE_NULL;
107
108 bRet = TRUE;
109 }
110 }
111 }
112 }
113 }
114
115 end:
116 if (hKey)
117 NtClose(hKey);
118
119 if (kvpInfo)
120 HeapFree(GetProcessHeap(), 0, kvpInfo);
121
122 return bRet;
123 }
124
125
126 VOID
127 LoadAppInitDlls()
128 {
129 szAppInit[0] = UNICODE_NULL;
130
131 if (GetDllList())
132 {
133 WCHAR buffer[KEY_LENGTH];
134 LPWSTR ptr;
135 size_t i;
136
137 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH);
138
139 for (i = 0; i < KEY_LENGTH; ++ i)
140 {
141 if(buffer[i] == L' ' || buffer[i] == L',')
142 buffer[i] = 0;
143 }
144
145 for (i = 0; i < KEY_LENGTH; )
146 {
147 if(buffer[i] == 0)
148 ++ i;
149 else
150 {
151 ptr = buffer + i;
152 i += wcslen(ptr);
153 LoadLibraryW(ptr);
154 }
155 }
156 }
157 }
158
159 VOID
160 UnloadAppInitDlls()
161 {
162 if (szAppInit[0] != UNICODE_NULL)
163 {
164 WCHAR buffer[KEY_LENGTH];
165 HMODULE hModule;
166 LPWSTR ptr;
167 size_t i;
168
169 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH);
170
171 for (i = 0; i < KEY_LENGTH; ++ i)
172 {
173 if(buffer[i] == L' ' || buffer[i] == L',')
174 buffer[i] = 0;
175 }
176
177 for (i = 0; i < KEY_LENGTH; )
178 {
179 if(buffer[i] == 0)
180 ++ i;
181 else
182 {
183 ptr = buffer + i;
184 i += wcslen(ptr);
185 hModule = GetModuleHandleW(ptr);
186 FreeLibrary(hModule);
187 }
188 }
189 }
190 }
191
192 BOOL
193 InitThread(VOID)
194 {
195 PUSER32_THREAD_DATA ThreadData;
196
197 ThreadData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
198 sizeof(USER32_THREAD_DATA));
199 if (ThreadData == NULL)
200 return FALSE;
201 if (!TlsSetValue(User32TlsIndex, ThreadData))
202 return FALSE;
203 return TRUE;
204 }
205
206 VOID
207 CleanupThread(VOID)
208 {
209 PUSER32_THREAD_DATA ThreadData;
210
211 ThreadData = (PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex);
212 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, ThreadData);
213 TlsSetValue(User32TlsIndex, 0);
214 }
215
216 BOOL
217 Init(VOID)
218 {
219 USERCONNECT UserCon;
220
221 /* Set up the kernel callbacks. */
222 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] =
223 (PVOID)User32CallWindowProcFromKernel;
224 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] =
225 (PVOID)User32CallSendAsyncProcForKernel;
226 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] =
227 (PVOID)User32LoadSysMenuTemplateForKernel;
228 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] =
229 (PVOID)User32SetupDefaultCursors;
230 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] =
231 (PVOID)User32CallHookProcFromKernel;
232 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_EVENTPROC] =
233 (PVOID)User32CallEventProcFromKernel;
234 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADMENU] =
235 (PVOID)User32CallLoadMenuFromKernel;
236 NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_CLIENTTHREADSTARTUP] =
237 (PVOID)User32CallClientThreadSetupFromKernel;
238
239 NtUserProcessConnect( NtCurrentProcess(),
240 &UserCon,
241 sizeof(USERCONNECT));
242
243 g_ppi = GetWin32ClientInfo()->ppi; // Snapshot PI, used as pointer only!
244 g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
245 gpsi = SharedPtrToUser(UserCon.siClient.psi);
246 gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
247 gHandleEntries = SharedPtrToUser(gHandleTable->handles);
248
249 RtlInitializeCriticalSection(&gcsUserApiHook);
250 gfServerProcess = TRUE; // FIXME HAX! Used in CsrClientConnectToServer(,,,,&gfServerProcess);
251
252 //ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", UserCon.siClient.psi, UserCon.siClient.aheList, g_ulSharedDelta);
253
254 /* Allocate an index for user32 thread local data. */
255 User32TlsIndex = TlsAlloc();
256 if (User32TlsIndex != TLS_OUT_OF_INDEXES)
257 {
258 if (MessageInit())
259 {
260 if (MenuInit())
261 {
262 InitializeCriticalSection(&U32AccelCacheLock);
263 GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
264 InitStockObjects();
265 LoadAppInitDlls();
266
267 return TRUE;
268 }
269 MessageCleanup();
270 }
271 TlsFree(User32TlsIndex);
272 }
273
274 return FALSE;
275 }
276
277 VOID
278 Cleanup(VOID)
279 {
280 DeleteCriticalSection(&U32AccelCacheLock);
281 MenuCleanup();
282 MessageCleanup();
283 DeleteFrameBrushes();
284 UnloadAppInitDlls();
285 GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
286 TlsFree(User32TlsIndex);
287 }
288
289 INT WINAPI
290 DllMain(
291 IN PVOID hInstanceDll,
292 IN ULONG dwReason,
293 IN PVOID reserved)
294 {
295 switch (dwReason)
296 {
297 case DLL_PROCESS_ATTACH:
298 User32Instance = hInstanceDll;
299 if (!RegisterClientPFN())
300 {
301 return FALSE;
302 }
303
304 if (!Init())
305 return FALSE;
306 if (!InitThread())
307 {
308 Cleanup();
309 return FALSE;
310 }
311
312 /* Initialize message spying */
313 if (!SPY_Init()) return FALSE;
314
315 break;
316
317 case DLL_THREAD_ATTACH:
318 if (!InitThread())
319 return FALSE;
320 break;
321
322 case DLL_THREAD_DETACH:
323 CleanupThread();
324 break;
325
326 case DLL_PROCESS_DETACH:
327 if (hImmInstance) FreeLibrary(hImmInstance);
328 CleanupThread();
329 Cleanup();
330 break;
331 }
332
333 return TRUE;
334 }
335
336
337 VOID
338 FASTCALL
339 GetConnected(VOID)
340 {
341 USERCONNECT UserCon;
342 // ERR("GetConnected\n");
343
344 if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo == NULL)
345 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
346
347 if (gpsi && g_ppi) return;
348 // FIXME HAX: Due to the "Dll Initialization Bug" we have to call this too.
349 GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
350
351 NtUserProcessConnect( NtCurrentProcess(),
352 &UserCon,
353 sizeof(USERCONNECT));
354
355 g_ppi = GetWin32ClientInfo()->ppi;
356 g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
357 gpsi = SharedPtrToUser(UserCon.siClient.psi);
358 gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
359 gHandleEntries = SharedPtrToUser(gHandleTable->handles);
360
361 }
362
363 NTSTATUS
364 WINAPI
365 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength)
366 {
367 ERR("GetConnected\n");
368 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
369 }
370