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
->ClassList
);
94 InitializeListHead(&Win32Process
->MenuListHead
);
96 InitializeListHead(&Win32Process
->GDIBrushAttrFreeList
);
97 InitializeListHead(&Win32Process
->GDIDcAttrFreeList
);
99 InitializeListHead(&Win32Process
->PrivateFontListHead
);
100 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
102 InitializeListHead(&Win32Process
->DriverObjListHead
);
103 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
105 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
106 EngCreateEvent((PEVENT
*)&Win32Process
->InputIdleEvent
);
107 KeInitializeEvent(Win32Process
->InputIdleEvent
, NotificationEvent
, FALSE
);
109 if(Process
->Peb
!= NULL
)
111 /* map the gdi handle table to user land */
112 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
113 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
116 Win32Process
->peProcess
= Process
;
117 /* setup process flags */
118 Win32Process
->W32PF_flags
= 0;
122 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
123 Win32Process
->W32PF_flags
|= W32PF_TERMINATED
;
124 if (Win32Process
->InputIdleEvent
)
126 EngFreeMem((PVOID
)Win32Process
->InputIdleEvent
);
127 Win32Process
->InputIdleEvent
= NULL
;
130 IntCleanupMenus(Process
, Win32Process
);
131 IntCleanupCurIcons(Process
, Win32Process
);
132 CleanupMonitorImpl();
134 /* no process windows should exist at this point, or the function will assert! */
135 DestroyProcessClasses(Win32Process
);
137 GDI_CleanupForProcess(Process
);
139 co_IntGraphicsCheck(FALSE
);
142 * Deregister logon application automatically
144 if(LogonProcess
== Win32Process
)
150 RETURN( STATUS_SUCCESS
);
154 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
161 Win32kThreadCallback(struct _ETHREAD
*Thread
,
162 PSW32THREADCALLOUTTYPE Type
)
164 struct _EPROCESS
*Process
;
165 PTHREADINFO Win32Thread
;
167 DECLARE_RETURN(NTSTATUS
);
169 DPRINT("Enter Win32kThreadCallback\n");
170 UserEnterExclusive();
172 Process
= Thread
->ThreadsProcess
;
174 /* Get the Win32 Thread */
175 Win32Thread
= PsGetThreadWin32Thread(Thread
);
177 /* Allocate one if needed */
180 /* FIXME - lock the process */
181 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
185 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
187 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
189 PsSetThreadWin32Thread(Thread
, Win32Thread
);
190 /* FIXME - unlock the process */
192 if (Type
== PsW32ThreadCalloutInitialize
)
194 HWINSTA hWinSta
= NULL
;
198 PUNICODE_STRING DesktopPath
;
199 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
201 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
203 InitializeListHead(&Win32Thread
->WindowListHead
);
204 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
205 InitializeListHead(&Win32Thread
->PtiLink
);
206 for (i
= 0; i
< NB_HOOKS
; i
++)
208 InitializeListHead(&Win32Thread
->aphkStart
[i
]);
212 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
213 * info structure. See documentation of CreateProcess()
215 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
216 Status
= IntParseDesktopPath(Process
,
220 if(NT_SUCCESS(Status
))
224 if(Process
!= CsrProcess
)
226 HWINSTA hProcessWinSta
= (HWINSTA
)InterlockedCompareExchangePointer((PVOID
)&Process
->Win32WindowStation
, (PVOID
)hWinSta
, NULL
);
227 if(hProcessWinSta
!= NULL
)
229 /* our process is already assigned to a different window station, we don't need the handle anymore */
241 PDESKTOP DesktopObject
;
242 Win32Thread
->rpdesk
= NULL
;
243 Status
= ObReferenceObjectByHandle(hDesk
,
247 (PVOID
*)&DesktopObject
,
250 if(NT_SUCCESS(Status
))
252 if (!IntSetThreadDesktop(DesktopObject
,
255 DPRINT1("Unable to set thread desktop\n");
260 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk
);
266 DPRINT1("No Desktop handle for this Thread!\n");
268 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
269 co_IntDestroyCaret(Win32Thread
);
270 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
271 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
272 Win32Thread
->ppi
->ptiList
= Win32Thread
;
273 Win32Thread
->ppi
->cThreads
++;
274 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
276 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
278 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
279 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
280 pTeb
= NtCurrentTeb();
282 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
283 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
284 Win32Thread
->pClientInfo
= pci
;
285 pci
->ppi
= Win32Thread
->ppi
;
286 pci
->fsHooks
= Win32Thread
->fsHooks
;
287 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
288 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
289 /* CI may not have been initialized. */
290 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
292 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
294 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
296 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
297 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
299 pci
->pClientThreadInfo
= NULL
;
303 DPRINT1("No TEB for this Thread!\n");
304 // System thread running! Now SendMessage should be okay.
305 Win32Thread
->pcti
= &Win32Thread
->cti
;
307 Win32Thread
->pEThread
= Thread
;
312 PSINGLE_LIST_ENTRY e
;
314 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
316 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
317 pti
= Win32Thread
->ppi
->ptiList
;
318 if (pti
== Win32Thread
)
320 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
321 Win32Thread
->ppi
->cThreads
--;
327 if (pti
->ptiSibling
== Win32Thread
)
329 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
330 Win32Thread
->ppi
->cThreads
--;
333 pti
= pti
->ptiSibling
;
337 DceFreeThreadDCE(Win32Thread
);
338 HOOK_DestroyThreadHooks(Thread
);
339 EVENT_DestroyThreadEvents(Thread
);
341 DestroyTimersForThread(Win32Thread
);
342 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
343 UnregisterThreadHotKeys(Thread
);
344 /* what if this co_ func crash in umode? what will clean us up then? */
345 co_DestroyThreadWindows(Thread
);
346 IntBlockInput(Win32Thread
, FALSE
);
347 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
348 IntCleanupThreadCallbacks(Win32Thread
);
350 /* cleanup user object references stack */
351 e
= PopEntryList(&Win32Thread
->ReferencesList
);
354 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
355 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
356 UserDereferenceObject(ref
->obj
);
358 e
= PopEntryList(&Win32Thread
->ReferencesList
);
361 IntSetThreadDesktop(NULL
, TRUE
);
363 PsSetThreadWin32Thread(Thread
, NULL
);
366 RETURN( STATUS_SUCCESS
);
370 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
375 Win32kInitWin32Thread(PETHREAD Thread
)
379 Process
= Thread
->ThreadsProcess
;
381 if (Process
->Win32Process
== NULL
)
383 /* FIXME - lock the process */
384 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
386 if (Process
->Win32Process
== NULL
)
387 return STATUS_NO_MEMORY
;
389 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
390 /* FIXME - unlock the process */
392 Win32kProcessCallback(Process
, TRUE
);
395 if (Thread
->Tcb
.Win32Thread
== NULL
)
397 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
398 if (Thread
->Tcb
.Win32Thread
== NULL
)
399 return STATUS_NO_MEMORY
;
401 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
403 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
406 return(STATUS_SUCCESS
);
409 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
414 if (!NT_SUCCESS(Status)) \
416 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
421 * This definition doesn't work
427 IN PDRIVER_OBJECT DriverObject
,
428 IN PUNICODE_STRING RegistryPath
)
432 WIN32_CALLOUTS_FPNS CalloutData
= {0};
433 PVOID GlobalUserHeapBase
= NULL
;
436 * Register user mode call interface
437 * (system service table index = 1)
439 Result
= KeAddSystemServiceTable(Win32kSSDT
,
441 Win32kNumberOfSysCalls
,
446 DPRINT1("Adding system services failed!\n");
447 return STATUS_UNSUCCESSFUL
;
450 hModuleWin
= MmPageEntireDriver(DriverEntry
);
451 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
453 /* Register Object Manager Callbacks */
454 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
455 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
456 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
457 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
458 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
459 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
461 /* Register our per-process and per-thread structures. */
462 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
464 /* Create the global USER heap */
465 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
467 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
468 if (GlobalUserHeap
== NULL
)
470 DPRINT1("Failed to initialize the global heap!\n");
471 return STATUS_UNSUCCESSFUL
;
474 /* Allocate global server info structure */
475 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
478 DPRINT1("Failed allocate server info structure!\n");
479 return STATUS_UNSUCCESSFUL
;
482 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
483 DPRINT("Global Server Data -> %x\n", gpsi
);
485 NT_ROF(InitGdiHandleTable());
486 NT_ROF(InitPaletteImpl());
488 /* Create stock objects, ie. precreated objects commonly
489 used by win32 applications */
490 CreateStockObjects();
491 CreateSysColorObjects();
493 NT_ROF(InitXlateImpl());
494 NT_ROF(InitPDEVImpl());
495 NT_ROF(InitLDEVImpl());
496 NT_ROF(InitDeviceImpl());
497 NT_ROF(InitDcImpl());
498 NT_ROF(InitUserImpl());
499 NT_ROF(InitHotkeyImpl());
500 NT_ROF(InitWindowStationImpl());
501 NT_ROF(InitDesktopImpl());
502 NT_ROF(InitWindowImpl());
503 NT_ROF(InitMenuImpl());
504 NT_ROF(InitInputImpl());
505 NT_ROF(InitKeyboardImpl());
506 NT_ROF(InitMonitorImpl());
507 NT_ROF(MsqInitializeImpl());
508 NT_ROF(InitTimerImpl());
509 NT_ROF(InitAcceleratorImpl());
510 NT_ROF(InitGuiCheckImpl());
512 /* Initialize FreeType library */
513 if (!InitFontSupport())
515 DPRINT1("Unable to initialize font support\n");
519 gusLanguageID
= IntGdiGetLanguageID();
521 return STATUS_SUCCESS
;