- Add flags for NtCreateProcessEx for upcoming patch.
[reactos.git] / reactos / subsys / win32k / main / dllmain.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * Entry Point for win32k.sys
22 */
23
24 #include <w32k.h>
25 #include <win32k/ntddraw.h>
26 #include <include/napi.h>
27
28 #define NDEBUG
29 #include <debug.h>
30
31 BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process);
32
33 extern ULONG_PTR Win32kSSDT[];
34 extern UCHAR Win32kSSPT[];
35 extern ULONG Win32kNumberOfSysCalls;
36
37 PSHARED_SECTION_POOL SessionSharedSectionPool = NULL;
38
39 NTSTATUS
40 STDCALL
41 Win32kProcessCallback(struct _EPROCESS *Process,
42 BOOLEAN Create)
43 {
44 PW32PROCESS Win32Process;
45 DECLARE_RETURN(NTSTATUS);
46
47 DPRINT("Enter Win32kProcessCallback\n");
48 UserEnterExclusive();
49
50 /* Get the Win32 Process */
51 Win32Process = PsGetProcessWin32Process(Process);
52
53 /* Allocate one if needed */
54 if (!Win32Process)
55 {
56 /* FIXME - lock the process */
57 Win32Process = ExAllocatePoolWithTag(NonPagedPool,
58 sizeof(W32PROCESS),
59 TAG('W', '3', '2', 'p'));
60
61 if (Win32Process == NULL) RETURN( STATUS_NO_MEMORY);
62
63 RtlZeroMemory(Win32Process, sizeof(W32PROCESS));
64
65 PsSetProcessWin32Process(Process, Win32Process);
66 /* FIXME - unlock the process */
67 }
68
69 if (Create)
70 {
71 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
72
73 InitializeListHead(&Win32Process->ClassList);
74
75 InitializeListHead(&Win32Process->MenuListHead);
76
77 InitializeListHead(&Win32Process->PrivateFontListHead);
78 ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
79
80 InitializeListHead(&Win32Process->DriverObjListHead);
81 ExInitializeFastMutex(&Win32Process->DriverObjListLock);
82
83 Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
84
85 if(Process->Peb != NULL)
86 {
87 /* map the gdi handle table to user land */
88 Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
89 }
90
91 /* setup process flags */
92 Win32Process->Flags = 0;
93 }
94 else
95 {
96 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
97 IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId);
98 IntCleanupMenus(Process, Win32Process);
99 IntCleanupCurIcons(Process, Win32Process);
100 IntEngCleanupDriverObjs(Process, Win32Process);
101 CleanupMonitorImpl();
102
103 /* no process windows should exist at this point, or the function will assert! */
104 DestroyProcessClasses(Win32Process);
105
106 GDI_CleanupForProcess(Process);
107
108 co_IntGraphicsCheck(FALSE);
109
110 /*
111 * Deregister logon application automatically
112 */
113 if(LogonProcess == Win32Process)
114 {
115 LogonProcess = NULL;
116 }
117 }
118
119 RETURN( STATUS_SUCCESS);
120
121 CLEANUP:
122 UserLeave();
123 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_);
124 END_CLEANUP;
125 }
126
127
128 NTSTATUS
129 STDCALL
130 Win32kThreadCallback(struct _ETHREAD *Thread,
131 BOOLEAN Create)
132 {
133 struct _EPROCESS *Process;
134 PW32THREAD Win32Thread;
135 DECLARE_RETURN(NTSTATUS);
136
137 DPRINT("Enter Win32kThreadCallback\n");
138 UserEnterExclusive();
139
140 Process = Thread->ThreadsProcess;
141
142 /* Get the Win32 Thread */
143 Win32Thread = PsGetThreadWin32Thread(Thread);
144
145 /* Allocate one if needed */
146 if (!Win32Thread)
147 {
148 /* FIXME - lock the process */
149 Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
150 sizeof(W32THREAD),
151 TAG('W', '3', '2', 't'));
152
153 if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
154
155 RtlZeroMemory(Win32Thread, sizeof(W32THREAD));
156
157 PsSetThreadWin32Thread(Thread, Win32Thread);
158 /* FIXME - unlock the process */
159 }
160 if (Create)
161 {
162 HWINSTA hWinSta = NULL;
163 HDESK hDesk = NULL;
164 NTSTATUS Status;
165 PUNICODE_STRING DesktopPath;
166 PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
167
168 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
169
170 /*
171 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
172 * info structure. See documentation of CreateProcess()
173 */
174 DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
175 Status = IntParseDesktopPath(Process,
176 DesktopPath,
177 &hWinSta,
178 &hDesk);
179 if(NT_SUCCESS(Status))
180 {
181 if(hWinSta != NULL)
182 {
183 if(Process != CsrProcess)
184 {
185 HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
186 if(hProcessWinSta != NULL)
187 {
188 /* our process is already assigned to a different window station, we don't need the handle anymore */
189 NtClose(hWinSta);
190 }
191 }
192 else
193 {
194 NtClose(hWinSta);
195 }
196 }
197
198 if (hDesk != NULL)
199 {
200 Status = ObReferenceObjectByHandle(hDesk,
201 0,
202 ExDesktopObjectType,
203 KernelMode,
204 (PVOID*)&Win32Thread->Desktop,
205 NULL);
206 NtClose(hDesk);
207 if(!NT_SUCCESS(Status))
208 {
209 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
210 Win32Thread->Desktop = NULL;
211 }
212 }
213 }
214 Win32Thread->IsExiting = FALSE;
215 co_IntDestroyCaret(Win32Thread);
216 Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
217 Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
218 Win32Thread->MessagePumpHookValue = 0;
219 InitializeListHead(&Win32Thread->WindowListHead);
220 InitializeListHead(&Win32Thread->W32CallbackListHead);
221 }
222 else
223 {
224 PSINGLE_LIST_ENTRY e;
225
226 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
227
228 Win32Thread->IsExiting = TRUE;
229 HOOK_DestroyThreadHooks(Thread);
230 UnregisterThreadHotKeys(Thread);
231 /* what if this co_ func crash in umode? what will clean us up then? */
232 co_DestroyThreadWindows(Thread);
233 IntBlockInput(Win32Thread, FALSE);
234 MsqDestroyMessageQueue(Win32Thread->MessageQueue);
235 IntCleanupThreadCallbacks(Win32Thread);
236 if(Win32Thread->Desktop != NULL)
237 {
238 ObDereferenceObject(Win32Thread->Desktop);
239 }
240
241 /* cleanup user object references stack */
242 e = PopEntryList(&Win32Thread->ReferencesList);
243 while (e)
244 {
245 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry);
246 DPRINT1("thread clean: remove reference obj 0x%x\n",ref->obj);
247 ObmDereferenceObject(ref->obj);
248
249 e = PopEntryList(&Win32Thread->ReferencesList);
250 }
251 PsSetThreadWin32Thread(Thread, NULL);
252 }
253
254 RETURN( STATUS_SUCCESS);
255
256 CLEANUP:
257 UserLeave();
258 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_);
259 END_CLEANUP;
260 }
261
262 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
263 not called there anymore, please delete */
264 NTSTATUS
265 Win32kInitWin32Thread(PETHREAD Thread)
266 {
267 PEPROCESS Process;
268
269 Process = Thread->ThreadsProcess;
270
271 if (Process->Win32Process == NULL)
272 {
273 /* FIXME - lock the process */
274 Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(W32PROCESS));
275
276 if (Process->Win32Process == NULL)
277 return STATUS_NO_MEMORY;
278
279 RtlZeroMemory(Process->Win32Process, sizeof(W32PROCESS));
280 /* FIXME - unlock the process */
281
282 Win32kProcessCallback(Process, TRUE);
283 }
284
285 if (Thread->Tcb.Win32Thread == NULL)
286 {
287 Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(W32THREAD));
288 if (Thread->Tcb.Win32Thread == NULL)
289 return STATUS_NO_MEMORY;
290
291 RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(W32THREAD));
292
293 Win32kThreadCallback(Thread, TRUE);
294 }
295
296 return(STATUS_SUCCESS);
297 }
298
299
300 /*
301 * This definition doesn't work
302 */
303 NTSTATUS STDCALL
304 DriverEntry (
305 IN PDRIVER_OBJECT DriverObject,
306 IN PUNICODE_STRING RegistryPath)
307 {
308 NTSTATUS Status;
309 BOOLEAN Result;
310 W32_CALLOUT_DATA CalloutData;
311
312 /*
313 * Register user mode call interface
314 * (system service table index = 1)
315 */
316 Result = KeAddSystemServiceTable (Win32kSSDT,
317 NULL,
318 Win32kNumberOfSysCalls,
319 Win32kSSPT,
320 1);
321 if (Result == FALSE)
322 {
323 DPRINT1("Adding system services failed!\n");
324 return STATUS_UNSUCCESSFUL;
325 }
326
327 /*
328 * Register Object Manager Callbacks
329 */
330 CalloutData.WinStaCreate = IntWinStaObjectOpen;
331 CalloutData.WinStaParse = IntWinStaObjectParse;
332 CalloutData.WinStaDelete = IntWinStaObjectDelete;
333 CalloutData.WinStaFind = IntWinStaObjectFind;
334 CalloutData.DesktopCreate = IntDesktopObjectCreate;
335 CalloutData.DesktopDelete = IntDesktopObjectDelete;
336 CalloutData.W32ProcessCallout = Win32kProcessCallback;
337 CalloutData.W32ThreadCallout = Win32kThreadCallback;
338
339 /*
340 * Register our per-process and per-thread structures.
341 */
342 PsEstablishWin32Callouts(&CalloutData);
343
344 Status = IntUserCreateSharedSectionPool(48 * 1024 * 1024, /* 48 MB by default */
345 &SessionSharedSectionPool);
346 if (!NT_SUCCESS(Status))
347 {
348 DPRINT1("Failed to initialize the shared section pool: Status 0x%x\n", Status);
349 }
350
351 Status = InitUserImpl();
352 if (!NT_SUCCESS(Status))
353 {
354 DPRINT1("Failed to initialize user implementation!\n");
355 return STATUS_UNSUCCESSFUL;
356 }
357
358 Status = InitHotkeyImpl();
359 if (!NT_SUCCESS(Status))
360 {
361 DPRINT1("Failed to initialize hotkey implementation!\n");
362 return STATUS_UNSUCCESSFUL;
363 }
364
365 Status = InitWindowStationImpl();
366 if (!NT_SUCCESS(Status))
367 {
368 DPRINT1("Failed to initialize window station implementation!\n");
369 return STATUS_UNSUCCESSFUL;
370 }
371
372 Status = InitClassImpl();
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT1("Failed to initialize window class implementation!\n");
376 return STATUS_UNSUCCESSFUL;
377 }
378
379 Status = InitDesktopImpl();
380 if (!NT_SUCCESS(Status))
381 {
382 DPRINT1("Failed to initialize desktop implementation!\n");
383 return STATUS_UNSUCCESSFUL;
384 }
385
386 Status = InitWindowImpl();
387 if (!NT_SUCCESS(Status))
388 {
389 DPRINT1("Failed to initialize window implementation!\n");
390 return STATUS_UNSUCCESSFUL;
391 }
392
393 Status = InitMenuImpl();
394 if (!NT_SUCCESS(Status))
395 {
396 DPRINT1("Failed to initialize menu implementation!\n");
397 return STATUS_UNSUCCESSFUL;
398 }
399
400 Status = InitInputImpl();
401 if (!NT_SUCCESS(Status))
402 {
403 DPRINT1("Failed to initialize input implementation.\n");
404 return(Status);
405 }
406
407 Status = InitKeyboardImpl();
408 if (!NT_SUCCESS(Status))
409 {
410 DPRINT1("Failed to initialize keyboard implementation.\n");
411 return(Status);
412 }
413
414 Status = InitMonitorImpl();
415 if (!NT_SUCCESS(Status))
416 {
417 DbgPrint("Failed to initialize monitor implementation!\n");
418 return STATUS_UNSUCCESSFUL;
419 }
420
421 Status = MsqInitializeImpl();
422 if (!NT_SUCCESS(Status))
423 {
424 DPRINT1("Failed to initialize message queue implementation.\n");
425 return(Status);
426 }
427
428 Status = InitTimerImpl();
429 if (!NT_SUCCESS(Status))
430 {
431 DPRINT1("Failed to initialize timer implementation.\n");
432 return(Status);
433 }
434
435 Status = InitAcceleratorImpl();
436 if (!NT_SUCCESS(Status))
437 {
438 DPRINT1("Failed to initialize accelerator implementation.\n");
439 return(Status);
440 }
441
442 Status = InitGuiCheckImpl();
443 if (!NT_SUCCESS(Status))
444 {
445 DPRINT1("Failed to initialize GUI check implementation.\n");
446 return(Status);
447 }
448
449 InitGdiObjectHandleTable ();
450
451 /* Initialize FreeType library */
452 if (! InitFontSupport())
453 {
454 DPRINT1("Unable to initialize font support\n");
455 return STATUS_UNSUCCESSFUL;
456 }
457
458 /* Create stock objects, ie. precreated objects commonly
459 used by win32 applications */
460 CreateStockObjects();
461 CreateSysColorObjects();
462
463 return STATUS_SUCCESS;
464 }
465
466
467 BOOLEAN STDCALL
468 Win32kInitialize (VOID)
469 {
470 return TRUE;
471 }
472
473 /* EOF */