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