2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Driver entry and initialization of win32k
5 * FILE: subsystems/win32/win32k/main/main.c
10 #include <include/napi.h>
17 PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT
*SectionObject
);
18 BOOL INTERNAL_CALL
GDI_CleanupForProcess (struct _EPROCESS
*Process
);
20 HANDLE GlobalUserHeap
= NULL
;
21 PSECTION_OBJECT GlobalUserHeapSection
= NULL
;
23 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
27 extern ULONG_PTR Win32kSSDT
[];
28 extern UCHAR Win32kSSPT
[];
29 extern ULONG Win32kNumberOfSysCalls
;
33 Win32kProcessCallback(struct _EPROCESS
*Process
,
36 PPROCESSINFO Win32Process
;
37 DECLARE_RETURN(NTSTATUS
);
39 DPRINT("Enter Win32kProcessCallback\n");
42 /* Get the Win32 Process */
43 Win32Process
= PsGetProcessWin32Process(Process
);
45 /* Allocate one if needed */
48 /* FIXME - lock the process */
49 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
53 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
55 RtlZeroMemory(Win32Process
, sizeof(PROCESSINFO
));
57 PsSetProcessWin32Process(Process
, Win32Process
);
58 /* FIXME - unlock the process */
65 PVOID UserBase
= NULL
;
67 extern PSECTION_OBJECT GlobalUserHeapSection
;
68 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
70 /* map the global heap into the process */
72 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
73 PsGetCurrentProcess(),
81 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
82 if (!NT_SUCCESS(Status
))
84 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
87 Win32Process
->HeapMappings
.Next
= NULL
;
88 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
89 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
90 Win32Process
->HeapMappings
.Count
= 1;
92 InitializeListHead(&Win32Process
->MenuListHead
);
94 InitializeListHead(&Win32Process
->GDIBrushAttrFreeList
);
95 InitializeListHead(&Win32Process
->GDIDcAttrFreeList
);
97 InitializeListHead(&Win32Process
->PrivateFontListHead
);
98 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
100 InitializeListHead(&Win32Process
->DriverObjListHead
);
101 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
103 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
104 EngCreateEvent((PEVENT
*)&Win32Process
->InputIdleEvent
);
105 KeInitializeEvent(Win32Process
->InputIdleEvent
, NotificationEvent
, FALSE
);
107 if(Process
->Peb
!= NULL
)
109 /* map the gdi handle table to user land */
110 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
111 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
114 Win32Process
->peProcess
= Process
;
115 /* setup process flags */
116 Win32Process
->W32PF_flags
= 0;
120 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
121 Win32Process
->W32PF_flags
|= W32PF_TERMINATED
;
122 if (Win32Process
->InputIdleEvent
)
124 EngFreeMem((PVOID
)Win32Process
->InputIdleEvent
);
125 Win32Process
->InputIdleEvent
= NULL
;
128 IntCleanupMenus(Process
, Win32Process
);
129 IntCleanupCurIcons(Process
, Win32Process
);
130 CleanupMonitorImpl();
132 /* no process windows should exist at this point, or the function will assert! */
133 DestroyProcessClasses(Win32Process
);
134 Win32Process
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
136 GDI_CleanupForProcess(Process
);
138 co_IntGraphicsCheck(FALSE
);
141 * Deregister logon application automatically
143 if(LogonProcess
== Win32Process
)
149 RETURN( STATUS_SUCCESS
);
153 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
160 Win32kThreadCallback(struct _ETHREAD
*Thread
,
161 PSW32THREADCALLOUTTYPE Type
)
163 struct _EPROCESS
*Process
;
164 PTHREADINFO Win32Thread
;
166 DECLARE_RETURN(NTSTATUS
);
168 DPRINT("Enter Win32kThreadCallback\n");
169 UserEnterExclusive();
171 Process
= Thread
->ThreadsProcess
;
173 /* Get the Win32 Thread */
174 Win32Thread
= PsGetThreadWin32Thread(Thread
);
176 /* Allocate one if needed */
179 /* FIXME - lock the process */
180 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
184 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
186 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
188 PsSetThreadWin32Thread(Thread
, Win32Thread
);
189 /* FIXME - unlock the process */
191 if (Type
== PsW32ThreadCalloutInitialize
)
193 HWINSTA hWinSta
= NULL
;
197 PUNICODE_STRING DesktopPath
;
198 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
200 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
202 InitializeListHead(&Win32Thread
->WindowListHead
);
203 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
204 InitializeListHead(&Win32Thread
->PtiLink
);
205 for (i
= 0; i
< NB_HOOKS
; i
++)
207 InitializeListHead(&Win32Thread
->aphkStart
[i
]);
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 DesktopObject
;
241 Win32Thread
->rpdesk
= 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
);
265 DPRINT1("No Desktop handle for this Thread!\n");
267 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
268 co_IntDestroyCaret(Win32Thread
);
269 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
270 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
271 Win32Thread
->ppi
->ptiList
= Win32Thread
;
272 Win32Thread
->ppi
->cThreads
++;
273 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
275 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
277 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
278 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
279 pTeb
= NtCurrentTeb();
281 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
282 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
283 Win32Thread
->pClientInfo
= pci
;
284 pci
->ppi
= Win32Thread
->ppi
;
285 pci
->fsHooks
= Win32Thread
->fsHooks
;
286 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
287 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
288 /* CI may not have been initialized. */
289 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
291 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
293 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
295 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
296 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
298 pci
->pClientThreadInfo
= NULL
;
302 DPRINT1("No TEB for this Thread!\n");
303 // System thread running! Now SendMessage should be okay.
304 Win32Thread
->pcti
= &Win32Thread
->cti
;
306 Win32Thread
->pEThread
= Thread
;
311 PSINGLE_LIST_ENTRY e
;
313 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
315 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
316 pti
= Win32Thread
->ppi
->ptiList
;
317 if (pti
== Win32Thread
)
319 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
320 Win32Thread
->ppi
->cThreads
--;
326 if (pti
->ptiSibling
== Win32Thread
)
328 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
329 Win32Thread
->ppi
->cThreads
--;
332 pti
= pti
->ptiSibling
;
336 DceFreeThreadDCE(Win32Thread
);
337 HOOK_DestroyThreadHooks(Thread
);
338 EVENT_DestroyThreadEvents(Thread
);
340 DestroyTimersForThread(Win32Thread
);
341 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
342 UnregisterThreadHotKeys(Thread
);
343 /* what if this co_ func crash in umode? what will clean us up then? */
344 co_DestroyThreadWindows(Thread
);
345 IntBlockInput(Win32Thread
, FALSE
);
346 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
347 IntCleanupThreadCallbacks(Win32Thread
);
349 /* cleanup user object references stack */
350 e
= PopEntryList(&Win32Thread
->ReferencesList
);
353 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
354 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
355 UserDereferenceObject(ref
->obj
);
357 e
= PopEntryList(&Win32Thread
->ReferencesList
);
360 IntSetThreadDesktop(NULL
, TRUE
);
362 PsSetThreadWin32Thread(Thread
, NULL
);
365 RETURN( STATUS_SUCCESS
);
369 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
374 Win32kInitWin32Thread(PETHREAD Thread
)
378 Process
= Thread
->ThreadsProcess
;
380 if (Process
->Win32Process
== NULL
)
382 /* FIXME - lock the process */
383 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
385 if (Process
->Win32Process
== NULL
)
386 return STATUS_NO_MEMORY
;
388 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
389 /* FIXME - unlock the process */
391 Win32kProcessCallback(Process
, TRUE
);
394 if (Thread
->Tcb
.Win32Thread
== NULL
)
396 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
397 if (Thread
->Tcb
.Win32Thread
== NULL
)
398 return STATUS_NO_MEMORY
;
400 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
402 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
405 return(STATUS_SUCCESS
);
408 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
413 if (!NT_SUCCESS(Status)) \
415 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
420 * This definition doesn't work
426 IN PDRIVER_OBJECT DriverObject
,
427 IN PUNICODE_STRING RegistryPath
)
431 WIN32_CALLOUTS_FPNS CalloutData
= {0};
432 PVOID GlobalUserHeapBase
= NULL
;
435 * Register user mode call interface
436 * (system service table index = 1)
438 Result
= KeAddSystemServiceTable(Win32kSSDT
,
440 Win32kNumberOfSysCalls
,
445 DPRINT1("Adding system services failed!\n");
446 return STATUS_UNSUCCESSFUL
;
449 hModuleWin
= MmPageEntireDriver(DriverEntry
);
450 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
452 /* Register Object Manager Callbacks */
453 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
454 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
455 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
456 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
457 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
458 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
460 /* Register our per-process and per-thread structures. */
461 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
463 /* Create the global USER heap */
464 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
466 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
467 if (GlobalUserHeap
== NULL
)
469 DPRINT1("Failed to initialize the global heap!\n");
470 return STATUS_UNSUCCESSFUL
;
473 /* Allocate global server info structure */
474 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
477 DPRINT1("Failed allocate server info structure!\n");
478 return STATUS_UNSUCCESSFUL
;
481 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
482 DPRINT("Global Server Data -> %x\n", gpsi
);
484 NT_ROF(InitGdiHandleTable());
485 NT_ROF(InitPaletteImpl());
487 /* Create stock objects, ie. precreated objects commonly
488 used by win32 applications */
489 CreateStockObjects();
490 CreateSysColorObjects();
492 NT_ROF(InitXlateImpl());
493 NT_ROF(InitPDEVImpl());
494 NT_ROF(InitLDEVImpl());
495 NT_ROF(InitDeviceImpl());
496 NT_ROF(InitDcImpl());
497 NT_ROF(InitUserImpl());
498 NT_ROF(InitHotkeyImpl());
499 NT_ROF(InitWindowStationImpl());
500 NT_ROF(InitDesktopImpl());
501 NT_ROF(InitWindowImpl());
502 NT_ROF(InitMenuImpl());
503 NT_ROF(InitInputImpl());
504 NT_ROF(InitKeyboardImpl());
505 NT_ROF(InitMonitorImpl());
506 NT_ROF(MsqInitializeImpl());
507 NT_ROF(InitTimerImpl());
508 NT_ROF(InitAcceleratorImpl());
509 NT_ROF(InitGuiCheckImpl());
511 /* Initialize FreeType library */
512 if (!InitFontSupport())
514 DPRINT1("Unable to initialize font support\n");
518 gusLanguageID
= IntGdiGetLanguageID();
520 return STATUS_SUCCESS
;