2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team
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.
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.
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.
21 * Entry Point for win32k.sys
25 #include <include/napi.h>
30 PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT
*SectionObject
);
31 BOOL INTERNAL_CALL
GDI_CleanupForProcess (PGDI_HANDLE_TABLE HandleTable
, struct _EPROCESS
*Process
);
33 PGDI_HANDLE_TABLE GdiHandleTable
= NULL
;
34 PSECTION_OBJECT GdiTableSection
= NULL
;
36 HANDLE GlobalUserHeap
= NULL
;
37 PSECTION_OBJECT GlobalUserHeapSection
= NULL
;
39 extern ULONG_PTR Win32kSSDT
[];
40 extern UCHAR Win32kSSPT
[];
41 extern ULONG Win32kNumberOfSysCalls
;
45 Win32kProcessCallback(struct _EPROCESS
*Process
,
48 PW32PROCESS Win32Process
;
49 DECLARE_RETURN(NTSTATUS
);
51 DPRINT("Enter Win32kProcessCallback\n");
54 /* Get the Win32 Process */
55 Win32Process
= PsGetProcessWin32Process(Process
);
57 /* Allocate one if needed */
60 /* FIXME - lock the process */
61 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
63 TAG('W', '3', '2', 'p'));
65 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
67 RtlZeroMemory(Win32Process
, sizeof(W32PROCESS
));
69 PsSetProcessWin32Process(Process
, Win32Process
);
70 /* FIXME - unlock the process */
77 PVOID UserBase
= NULL
;
79 extern PSECTION_OBJECT GlobalUserHeapSection
;
80 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
82 /* map the global heap into the process */
84 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
85 PsGetCurrentProcess(),
93 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
94 if (!NT_SUCCESS(Status
))
96 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
99 Win32Process
->HeapMappings
.Next
= NULL
;
100 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
101 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
102 Win32Process
->HeapMappings
.Count
= 1;
104 InitializeListHead(&Win32Process
->ClassList
);
106 InitializeListHead(&Win32Process
->MenuListHead
);
108 InitializeListHead(&Win32Process
->PrivateFontListHead
);
109 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
111 InitializeListHead(&Win32Process
->DriverObjListHead
);
112 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
114 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
116 if(Process
->Peb
!= NULL
)
118 /* map the gdi handle table to user land */
119 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
120 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
123 /* setup process flags */
124 Win32Process
->Flags
= 0;
128 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
129 IntCleanupMenus(Process
, Win32Process
);
130 IntCleanupCurIcons(Process
, Win32Process
);
131 IntEngCleanupDriverObjs(Process
, Win32Process
);
132 CleanupMonitorImpl();
134 /* no process windows should exist at this point, or the function will assert! */
135 DestroyProcessClasses(Win32Process
);
137 GDI_CleanupForProcess(GdiHandleTable
, Process
);
139 co_IntGraphicsCheck(FALSE
);
142 * Deregister logon application automatically
144 if(LogonProcess
== Win32Process
)
149 if (Win32Process
->ProcessInfo
!= NULL
)
151 UserHeapFree(Win32Process
->ProcessInfo
);
152 Win32Process
->ProcessInfo
= NULL
;
156 RETURN( STATUS_SUCCESS
);
160 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
167 Win32kThreadCallback(struct _ETHREAD
*Thread
,
168 PSW32THREADCALLOUTTYPE Type
)
170 struct _EPROCESS
*Process
;
171 PW32THREAD Win32Thread
;
172 DECLARE_RETURN(NTSTATUS
);
174 DPRINT("Enter Win32kThreadCallback\n");
175 UserEnterExclusive();
177 Process
= Thread
->ThreadsProcess
;
179 /* Get the Win32 Thread */
180 Win32Thread
= PsGetThreadWin32Thread(Thread
);
182 /* Allocate one if needed */
185 /* FIXME - lock the process */
186 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
188 TAG('W', '3', '2', 't'));
190 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
192 RtlZeroMemory(Win32Thread
, sizeof(W32THREAD
));
194 PsSetThreadWin32Thread(Thread
, Win32Thread
);
195 /* FIXME - unlock the process */
197 if (Type
== PsW32ThreadCalloutInitialize
)
199 HWINSTA hWinSta
= NULL
;
202 PUNICODE_STRING DesktopPath
;
203 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
205 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
207 InitializeListHead(&Win32Thread
->WindowListHead
);
208 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
211 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
212 * info structure. See documentation of CreateProcess()
214 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
215 Status
= IntParseDesktopPath(Process
,
219 if(NT_SUCCESS(Status
))
223 if(Process
!= CsrProcess
)
225 HWINSTA hProcessWinSta
= (HWINSTA
)InterlockedCompareExchangePointer((PVOID
)&Process
->Win32WindowStation
, (PVOID
)hWinSta
, NULL
);
226 if(hProcessWinSta
!= NULL
)
228 /* our process is already assigned to a different window station, we don't need the handle anymore */
240 PDESKTOP_OBJECT DesktopObject
;
241 Win32Thread
->Desktop
= NULL
;
242 Status
= ObReferenceObjectByHandle(hDesk
,
246 (PVOID
*)&DesktopObject
,
249 if(NT_SUCCESS(Status
))
251 if (!IntSetThreadDesktop(DesktopObject
,
254 DPRINT1("Unable to set thread desktop\n");
259 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk
);
263 Win32Thread
->IsExiting
= FALSE
;
264 co_IntDestroyCaret(Win32Thread
);
265 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
266 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
267 Win32Thread
->MessagePumpHookValue
= 0;
271 PSINGLE_LIST_ENTRY e
;
273 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
275 Win32Thread
->IsExiting
= TRUE
;
276 HOOK_DestroyThreadHooks(Thread
);
277 UnregisterThreadHotKeys(Thread
);
278 /* what if this co_ func crash in umode? what will clean us up then? */
279 co_DestroyThreadWindows(Thread
);
280 IntBlockInput(Win32Thread
, FALSE
);
281 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
282 IntCleanupThreadCallbacks(Win32Thread
);
284 /* cleanup user object references stack */
285 e
= PopEntryList(&Win32Thread
->ReferencesList
);
288 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
289 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
290 ObmDereferenceObject(ref
->obj
);
292 e
= PopEntryList(&Win32Thread
->ReferencesList
);
295 IntSetThreadDesktop(NULL
,
298 if (Win32Thread
->ThreadInfo
!= NULL
)
300 UserHeapFree(Win32Thread
->ThreadInfo
);
301 Win32Thread
->ThreadInfo
= NULL
;
304 PsSetThreadWin32Thread(Thread
, NULL
);
307 RETURN( STATUS_SUCCESS
);
311 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
315 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
316 not called there anymore, please delete */
318 Win32kInitWin32Thread(PETHREAD Thread
)
322 Process
= Thread
->ThreadsProcess
;
324 if (Process
->Win32Process
== NULL
)
326 /* FIXME - lock the process */
327 Process
->Win32Process
= ExAllocatePool(NonPagedPool
, sizeof(W32PROCESS
));
329 if (Process
->Win32Process
== NULL
)
330 return STATUS_NO_MEMORY
;
332 RtlZeroMemory(Process
->Win32Process
, sizeof(W32PROCESS
));
333 /* FIXME - unlock the process */
335 Win32kProcessCallback(Process
, TRUE
);
338 if (Thread
->Tcb
.Win32Thread
== NULL
)
340 Thread
->Tcb
.Win32Thread
= ExAllocatePool (NonPagedPool
, sizeof(W32THREAD
));
341 if (Thread
->Tcb
.Win32Thread
== NULL
)
342 return STATUS_NO_MEMORY
;
344 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(W32THREAD
));
346 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
349 return(STATUS_SUCCESS
);
354 * This definition doesn't work
358 IN PDRIVER_OBJECT DriverObject
,
359 IN PUNICODE_STRING RegistryPath
)
363 WIN32_CALLOUTS_FPNS CalloutData
= {0};
364 PVOID GlobalUserHeapBase
= NULL
;
367 * Register user mode call interface
368 * (system service table index = 1)
370 Result
= KeAddSystemServiceTable (Win32kSSDT
,
372 Win32kNumberOfSysCalls
,
377 DPRINT1("Adding system services failed!\n");
378 return STATUS_UNSUCCESSFUL
;
382 * Register Object Manager Callbacks
384 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
385 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
386 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
387 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
388 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
389 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
392 * Register our per-process and per-thread structures.
394 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
396 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
398 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
399 if (GlobalUserHeap
== NULL
)
401 DPRINT1("Failed to initialize the global heap!\n");
402 return STATUS_UNSUCCESSFUL
;
406 Status
= InitUserImpl();
407 if (!NT_SUCCESS(Status
))
409 DPRINT1("Failed to initialize user implementation!\n");
410 return STATUS_UNSUCCESSFUL
;
413 Status
= InitHotkeyImpl();
414 if (!NT_SUCCESS(Status
))
416 DPRINT1("Failed to initialize hotkey implementation!\n");
417 return STATUS_UNSUCCESSFUL
;
420 Status
= InitWindowStationImpl();
421 if (!NT_SUCCESS(Status
))
423 DPRINT1("Failed to initialize window station implementation!\n");
424 return STATUS_UNSUCCESSFUL
;
427 Status
= InitDesktopImpl();
428 if (!NT_SUCCESS(Status
))
430 DPRINT1("Failed to initialize desktop implementation!\n");
431 return STATUS_UNSUCCESSFUL
;
434 Status
= InitWindowImpl();
435 if (!NT_SUCCESS(Status
))
437 DPRINT1("Failed to initialize window implementation!\n");
438 return STATUS_UNSUCCESSFUL
;
441 Status
= InitMenuImpl();
442 if (!NT_SUCCESS(Status
))
444 DPRINT1("Failed to initialize menu implementation!\n");
445 return STATUS_UNSUCCESSFUL
;
448 Status
= InitInputImpl();
449 if (!NT_SUCCESS(Status
))
451 DPRINT1("Failed to initialize input implementation.\n");
455 Status
= InitKeyboardImpl();
456 if (!NT_SUCCESS(Status
))
458 DPRINT1("Failed to initialize keyboard implementation.\n");
462 Status
= InitMonitorImpl();
463 if (!NT_SUCCESS(Status
))
465 DbgPrint("Failed to initialize monitor implementation!\n");
466 return STATUS_UNSUCCESSFUL
;
469 Status
= MsqInitializeImpl();
470 if (!NT_SUCCESS(Status
))
472 DPRINT1("Failed to initialize message queue implementation.\n");
476 Status
= InitTimerImpl();
477 if (!NT_SUCCESS(Status
))
479 DPRINT1("Failed to initialize timer implementation.\n");
483 Status
= InitAcceleratorImpl();
484 if (!NT_SUCCESS(Status
))
486 DPRINT1("Failed to initialize accelerator implementation.\n");
490 Status
= InitGuiCheckImpl();
491 if (!NT_SUCCESS(Status
))
493 DPRINT1("Failed to initialize GUI check implementation.\n");
497 GdiHandleTable
= GDIOBJ_iAllocHandleTable(&GdiTableSection
);
498 if (GdiHandleTable
== NULL
)
500 DPRINT1("Failed to initialize the GDI handle table.\n");
501 return STATUS_UNSUCCESSFUL
;
504 Status
= InitDcImpl();
505 if (!NT_SUCCESS(Status
))
507 DPRINT1("Failed to initialize Device context implementation!\n");
508 return STATUS_UNSUCCESSFUL
;
511 /* Initialize FreeType library */
512 if (! InitFontSupport())
514 DPRINT1("Unable to initialize font support\n");
515 return STATUS_UNSUCCESSFUL
;
518 /* Create stock objects, ie. precreated objects commonly
519 used by win32 applications */
520 CreateStockObjects();
521 CreateSysColorObjects();
523 return STATUS_SUCCESS
;
528 Win32kInitialize (VOID
)