Create a branch for network fixes.
[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 PUSER_HANDLE_TABLE gHandleTable = NULL;
11 PUSER_HANDLE_ENTRY gHandleEntries = NULL;
12 PW32PROCESSINFO g_pi = NULL; /* User Mode Pointer */
13 PW32PROCESSINFO g_kpi = NULL; /* Kernel Mode Pointer */
14 PSERVERINFO g_psi = NULL;
15 WCHAR szAppInit[KEY_LENGTH];
16
17 PW32PROCESSINFO
18 GetW32ProcessInfo(VOID);
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 LPWSTR seps = L" ,";
136
137 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH);;
138
139 ptr = wcstok(buffer, seps);
140 while (ptr)
141 {
142 LoadLibraryW(ptr);
143 ptr = wcstok(NULL, seps);
144 }
145 }
146 }
147
148 VOID
149 UnloadAppInitDlls()
150 {
151 if (szAppInit[0] != UNICODE_NULL)
152 {
153 WCHAR buffer[KEY_LENGTH];
154 HMODULE hModule;
155 LPWSTR ptr;
156 LPWSTR seps = L" ,";
157
158 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH);
159
160 ptr = wcstok(buffer, seps);
161 while (ptr)
162 {
163 hModule = GetModuleHandleW(ptr);
164 FreeLibrary(hModule);
165 ptr = wcstok(NULL, seps);
166 }
167 }
168 }
169
170 BOOL
171 InitThread(VOID)
172 {
173 PUSER32_THREAD_DATA ThreadData;
174
175 ThreadData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
176 sizeof(USER32_THREAD_DATA));
177 if (ThreadData == NULL)
178 return FALSE;
179 if (!TlsSetValue(User32TlsIndex, ThreadData))
180 return FALSE;
181 return TRUE;
182 }
183
184 VOID
185 CleanupThread(VOID)
186 {
187 PUSER32_THREAD_DATA ThreadData;
188
189 ThreadData = (PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex);
190 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, ThreadData);
191 TlsSetValue(User32TlsIndex, 0);
192 }
193
194 BOOL
195 Init(VOID)
196 {
197 /* Set up the kernel callbacks. */
198 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] =
199 (PVOID)User32CallWindowProcFromKernel;
200 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] =
201 (PVOID)User32CallSendAsyncProcForKernel;
202 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] =
203 (PVOID)User32LoadSysMenuTemplateForKernel;
204 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] =
205 (PVOID)User32SetupDefaultCursors;
206 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] =
207 (PVOID)User32CallHookProcFromKernel;
208 NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_EVENTPROC] =
209 (PVOID)User32CallEventProcFromKernel;
210
211 g_pi = GetW32ProcessInfo();
212 g_kpi = SharedPtrToKernel(g_pi);
213 g_psi = SharedPtrToUser(g_pi->psi);
214 gHandleTable = SharedPtrToUser(g_pi->UserHandleTable);
215 gHandleEntries = SharedPtrToUser(gHandleTable->handles);
216
217 /* Allocate an index for user32 thread local data. */
218 User32TlsIndex = TlsAlloc();
219 if (User32TlsIndex != TLS_OUT_OF_INDEXES)
220 {
221 if (MessageInit())
222 {
223 if (MenuInit())
224 {
225 InitializeCriticalSection(&U32AccelCacheLock);
226 GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
227 InitStockObjects();
228 LoadAppInitDlls();
229
230 return TRUE;
231 }
232 MessageCleanup();
233 }
234 TlsFree(User32TlsIndex);
235 }
236
237 return FALSE;
238 }
239
240 VOID
241 Cleanup(VOID)
242 {
243 DeleteCriticalSection(&U32AccelCacheLock);
244 MenuCleanup();
245 MessageCleanup();
246 DeleteFrameBrushes();
247 UnloadAppInitDlls();
248 GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
249 TlsFree(User32TlsIndex);
250 }
251
252 INT STDCALL
253 DllMain(
254 IN PVOID hInstanceDll,
255 IN ULONG dwReason,
256 IN PVOID reserved)
257 {
258 switch (dwReason)
259 {
260 case DLL_PROCESS_ATTACH:
261 User32Instance = hInstanceDll;
262 if (!NtUserRegisterUserModule(hInstanceDll) ||
263 !RegisterSystemControls())
264 {
265 return FALSE;
266 }
267
268 if (!Init())
269 return FALSE;
270 if (!InitThread())
271 {
272 Cleanup();
273 return FALSE;
274 }
275
276 /* Initialize message spying */
277 if (!SPY_Init()) return FALSE;
278
279 break;
280
281 case DLL_THREAD_ATTACH:
282 if (!InitThread())
283 return FALSE;
284 break;
285
286 case DLL_THREAD_DETACH:
287 CleanupThread();
288 break;
289
290 case DLL_PROCESS_DETACH:
291 CleanupThread();
292 Cleanup();
293 break;
294 }
295
296 return TRUE;
297 }
298
299
300 VOID
301 FASTCALL
302 GetConnected(VOID)
303 {
304 PW32PROCESSINFO pi;
305
306 if ((PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo == NULL)
307 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
308
309 if (g_pi && g_kpi && g_psi) return;
310
311 pi = GetW32ProcessInfo();
312 if (!g_pi) g_pi = pi;
313 if (!g_kpi) g_kpi = SharedPtrToKernel(pi);
314 if (!g_psi) g_psi = SharedPtrToUser(pi->psi);
315 if (!g_psi) { WARN("Global Share Information has not been initialized!\n"); }
316 if (!gHandleTable) gHandleTable = SharedPtrToUser(pi->UserHandleTable);
317 if (!gHandleEntries) gHandleEntries = SharedPtrToUser(gHandleTable->handles);
318
319 }