Sync with trunk head.
[reactos.git] / 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 PVOID *KernelCallbackTable;
221
222 /* Set up the kernel callbacks. */
223 KernelCallbackTable = NtCurrentPeb()->KernelCallbackTable;
224 KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] =
225 (PVOID)User32CallWindowProcFromKernel;
226 KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] =
227 (PVOID)User32CallSendAsyncProcForKernel;
228 KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] =
229 (PVOID)User32LoadSysMenuTemplateForKernel;
230 KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] =
231 (PVOID)User32SetupDefaultCursors;
232 KernelCallbackTable[USER32_CALLBACK_HOOKPROC] =
233 (PVOID)User32CallHookProcFromKernel;
234 KernelCallbackTable[USER32_CALLBACK_EVENTPROC] =
235 (PVOID)User32CallEventProcFromKernel;
236 KernelCallbackTable[USER32_CALLBACK_LOADMENU] =
237 (PVOID)User32CallLoadMenuFromKernel;
238 KernelCallbackTable[USER32_CALLBACK_CLIENTTHREADSTARTUP] =
239 (PVOID)User32CallClientThreadSetupFromKernel;
240
241 NtUserProcessConnect( NtCurrentProcess(),
242 &UserCon,
243 sizeof(USERCONNECT));
244
245 g_ppi = GetWin32ClientInfo()->ppi; // Snapshot PI, used as pointer only!
246 g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
247 gpsi = SharedPtrToUser(UserCon.siClient.psi);
248 gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
249 gHandleEntries = SharedPtrToUser(gHandleTable->handles);
250
251 RtlInitializeCriticalSection(&gcsUserApiHook);
252 gfServerProcess = TRUE; // FIXME HAX! Used in CsrClientConnectToServer(,,,,&gfServerProcess);
253
254 //ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", UserCon.siClient.psi, UserCon.siClient.aheList, g_ulSharedDelta);
255
256 /* Allocate an index for user32 thread local data. */
257 User32TlsIndex = TlsAlloc();
258 if (User32TlsIndex != TLS_OUT_OF_INDEXES)
259 {
260 if (MessageInit())
261 {
262 if (MenuInit())
263 {
264 InitializeCriticalSection(&U32AccelCacheLock);
265 GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
266 InitStockObjects();
267 LoadAppInitDlls();
268
269 return TRUE;
270 }
271 MessageCleanup();
272 }
273 TlsFree(User32TlsIndex);
274 }
275
276 return FALSE;
277 }
278
279 VOID
280 Cleanup(VOID)
281 {
282 DeleteCriticalSection(&U32AccelCacheLock);
283 MenuCleanup();
284 MessageCleanup();
285 DeleteFrameBrushes();
286 UnloadAppInitDlls();
287 GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
288 TlsFree(User32TlsIndex);
289 }
290
291 INT WINAPI
292 DllMain(
293 IN PVOID hInstanceDll,
294 IN ULONG dwReason,
295 IN PVOID reserved)
296 {
297 switch (dwReason)
298 {
299 case DLL_PROCESS_ATTACH:
300 User32Instance = hInstanceDll;
301 if (!RegisterClientPFN())
302 {
303 return FALSE;
304 }
305
306 if (!Init())
307 return FALSE;
308 if (!InitThread())
309 {
310 Cleanup();
311 return FALSE;
312 }
313
314 /* Initialize message spying */
315 if (!SPY_Init()) return FALSE;
316
317 break;
318
319 case DLL_THREAD_ATTACH:
320 if (!InitThread())
321 return FALSE;
322 break;
323
324 case DLL_THREAD_DETACH:
325 CleanupThread();
326 break;
327
328 case DLL_PROCESS_DETACH:
329 if (hImmInstance) FreeLibrary(hImmInstance);
330 CleanupThread();
331 Cleanup();
332 break;
333 }
334
335 return TRUE;
336 }
337
338
339 VOID
340 FASTCALL
341 GetConnected(VOID)
342 {
343 USERCONNECT UserCon;
344 // ERR("GetConnected\n");
345
346 if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo == NULL)
347 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
348
349 if (gpsi && g_ppi) return;
350 // FIXME HAX: Due to the "Dll Initialization Bug" we have to call this too.
351 GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
352
353 NtUserProcessConnect( NtCurrentProcess(),
354 &UserCon,
355 sizeof(USERCONNECT));
356
357 g_ppi = GetWin32ClientInfo()->ppi;
358 g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
359 gpsi = SharedPtrToUser(UserCon.siClient.psi);
360 gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
361 gHandleEntries = SharedPtrToUser(gHandleTable->handles);
362
363 }
364
365 NTSTATUS
366 WINAPI
367 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength)
368 {
369 ERR("GetConnected\n");
370 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
371 }
372