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