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 Win32Thread
->rpdesk
= NULL
;
241 Win32Thread
->hdesk
= NULL
;
242 if (!IntSetThreadDesktop(hDesk
, FALSE
))
244 DPRINT1("Unable to set thread desktop\n");
250 DPRINT1("No Desktop handle for this Thread!\n");
252 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
253 co_IntDestroyCaret(Win32Thread
);
254 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
255 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
256 Win32Thread
->ppi
->ptiList
= Win32Thread
;
257 Win32Thread
->ppi
->cThreads
++;
258 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
260 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
262 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
263 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
264 pTeb
= NtCurrentTeb();
266 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
267 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
268 Win32Thread
->pClientInfo
= pci
;
269 pci
->ppi
= Win32Thread
->ppi
;
270 pci
->fsHooks
= Win32Thread
->fsHooks
;
271 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
272 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
273 /* CI may not have been initialized. */
274 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
276 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
278 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
280 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
281 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
283 pci
->pClientThreadInfo
= NULL
;
287 DPRINT1("No TEB for this Thread!\n");
288 // System thread running! Now SendMessage should be okay.
289 Win32Thread
->pcti
= &Win32Thread
->cti
;
291 Win32Thread
->pEThread
= Thread
;
296 PSINGLE_LIST_ENTRY e
;
298 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
300 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
301 pti
= Win32Thread
->ppi
->ptiList
;
302 if (pti
== Win32Thread
)
304 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
305 Win32Thread
->ppi
->cThreads
--;
311 if (pti
->ptiSibling
== Win32Thread
)
313 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
314 Win32Thread
->ppi
->cThreads
--;
317 pti
= pti
->ptiSibling
;
321 DceFreeThreadDCE(Win32Thread
);
322 HOOK_DestroyThreadHooks(Thread
);
323 EVENT_DestroyThreadEvents(Thread
);
325 DestroyTimersForThread(Win32Thread
);
326 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
327 UnregisterThreadHotKeys(Thread
);
328 /* what if this co_ func crash in umode? what will clean us up then? */
329 co_DestroyThreadWindows(Thread
);
330 IntBlockInput(Win32Thread
, FALSE
);
331 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
332 IntCleanupThreadCallbacks(Win32Thread
);
334 /* cleanup user object references stack */
335 e
= PopEntryList(&Win32Thread
->ReferencesList
);
338 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
339 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
340 UserDereferenceObject(ref
->obj
);
342 e
= PopEntryList(&Win32Thread
->ReferencesList
);
345 IntSetThreadDesktop(NULL
, TRUE
);
347 PsSetThreadWin32Thread(Thread
, NULL
);
350 RETURN( STATUS_SUCCESS
);
354 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
359 Win32kInitWin32Thread(PETHREAD Thread
)
363 Process
= Thread
->ThreadsProcess
;
365 if (Process
->Win32Process
== NULL
)
367 /* FIXME - lock the process */
368 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
370 if (Process
->Win32Process
== NULL
)
371 return STATUS_NO_MEMORY
;
373 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
374 /* FIXME - unlock the process */
376 Win32kProcessCallback(Process
, TRUE
);
379 if (Thread
->Tcb
.Win32Thread
== NULL
)
381 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
382 if (Thread
->Tcb
.Win32Thread
== NULL
)
383 return STATUS_NO_MEMORY
;
385 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
387 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
390 return(STATUS_SUCCESS
);
393 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
398 if (!NT_SUCCESS(Status)) \
400 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
405 * This definition doesn't work
411 IN PDRIVER_OBJECT DriverObject
,
412 IN PUNICODE_STRING RegistryPath
)
416 WIN32_CALLOUTS_FPNS CalloutData
= {0};
417 PVOID GlobalUserHeapBase
= NULL
;
420 * Register user mode call interface
421 * (system service table index = 1)
423 Result
= KeAddSystemServiceTable(Win32kSSDT
,
425 Win32kNumberOfSysCalls
,
430 DPRINT1("Adding system services failed!\n");
431 return STATUS_UNSUCCESSFUL
;
434 hModuleWin
= MmPageEntireDriver(DriverEntry
);
435 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
437 /* Register Object Manager Callbacks */
438 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
439 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
440 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
441 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
442 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
443 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
445 /* Register our per-process and per-thread structures. */
446 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
449 /* Register service hook callbacks */
450 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
451 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
454 /* Create the global USER heap */
455 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
457 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
458 if (GlobalUserHeap
== NULL
)
460 DPRINT1("Failed to initialize the global heap!\n");
461 return STATUS_UNSUCCESSFUL
;
464 /* Allocate global server info structure */
465 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
468 DPRINT1("Failed allocate server info structure!\n");
469 return STATUS_UNSUCCESSFUL
;
472 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
473 DPRINT("Global Server Data -> %x\n", gpsi
);
475 NT_ROF(InitGdiHandleTable());
476 NT_ROF(InitPaletteImpl());
478 /* Create stock objects, ie. precreated objects commonly
479 used by win32 applications */
480 CreateStockObjects();
481 CreateSysColorObjects();
483 NT_ROF(InitXlateImpl());
484 NT_ROF(InitPDEVImpl());
485 NT_ROF(InitLDEVImpl());
486 NT_ROF(InitDeviceImpl());
487 NT_ROF(InitDcImpl());
488 NT_ROF(InitUserImpl());
489 NT_ROF(InitHotkeyImpl());
490 NT_ROF(InitWindowStationImpl());
491 NT_ROF(InitDesktopImpl());
492 NT_ROF(InitWindowImpl());
493 NT_ROF(InitMenuImpl());
494 NT_ROF(InitInputImpl());
495 NT_ROF(InitKeyboardImpl());
496 NT_ROF(InitMonitorImpl());
497 NT_ROF(MsqInitializeImpl());
498 NT_ROF(InitTimerImpl());
499 NT_ROF(InitAcceleratorImpl());
500 NT_ROF(InitGuiCheckImpl());
502 /* Initialize FreeType library */
503 if (!InitFontSupport())
505 DPRINT1("Unable to initialize font support\n");
509 gusLanguageID
= IntGdiGetLanguageID();
511 return STATUS_SUCCESS
;