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(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
;
123 if (Win32Process
->InputIdleEvent
)
125 EngFreeMem((PVOID
)Win32Process
->InputIdleEvent
);
126 Win32Process
->InputIdleEvent
= NULL
;
129 IntCleanupMenus(Process
, Win32Process
);
130 IntCleanupCurIcons(Process
, Win32Process
);
131 CleanupMonitorImpl();
133 /* no process windows should exist at this point, or the function will assert! */
134 DestroyProcessClasses(Win32Process
);
135 Win32Process
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
137 GDI_CleanupForProcess(Process
);
139 co_IntGraphicsCheck(FALSE
);
142 * Deregister logon application automatically
144 if(LogonProcess
== Win32Process
)
149 UserSetProcessWindowStation(NULL
);
153 RETURN( STATUS_SUCCESS
);
157 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
164 Win32kThreadCallback(struct _ETHREAD
*Thread
,
165 PSW32THREADCALLOUTTYPE Type
)
167 struct _EPROCESS
*Process
;
168 PTHREADINFO Win32Thread
;
170 DECLARE_RETURN(NTSTATUS
);
172 DPRINT("Enter Win32kThreadCallback\n");
173 UserEnterExclusive();
175 Process
= Thread
->ThreadsProcess
;
177 /* Get the Win32 Thread */
178 Win32Thread
= PsGetThreadWin32Thread(Thread
);
180 /* Allocate one if needed */
183 /* FIXME - lock the process */
184 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
188 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
190 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
192 PsSetThreadWin32Thread(Thread
, Win32Thread
);
193 /* FIXME - unlock the process */
195 if (Type
== PsW32ThreadCalloutInitialize
)
197 HWINSTA hWinSta
= NULL
;
201 PUNICODE_STRING DesktopPath
;
202 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
204 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
206 InitializeListHead(&Win32Thread
->WindowListHead
);
207 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
208 InitializeListHead(&Win32Thread
->PtiLink
);
209 for (i
= 0; i
< NB_HOOKS
; i
++)
211 InitializeListHead(&Win32Thread
->aphkStart
[i
]);
215 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
216 * info structure. See documentation of CreateProcess()
218 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
219 Status
= IntParseDesktopPath(Process
,
223 if(NT_SUCCESS(Status
))
227 if(!UserSetProcessWindowStation(hWinSta
))
229 DPRINT1("Failed to set process window station\n");
235 if (!IntSetThreadDesktop(hDesk
, FALSE
))
237 DPRINT1("Unable to set thread desktop\n");
243 DPRINT1("No Desktop handle for this Thread!\n");
245 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
246 co_IntDestroyCaret(Win32Thread
);
247 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
248 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
249 Win32Thread
->ppi
->ptiList
= Win32Thread
;
250 Win32Thread
->ppi
->cThreads
++;
251 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
253 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
255 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
256 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
257 pTeb
= NtCurrentTeb();
259 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
260 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
261 Win32Thread
->pClientInfo
= pci
;
262 pci
->ppi
= Win32Thread
->ppi
;
263 pci
->fsHooks
= Win32Thread
->fsHooks
;
264 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
265 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
266 /* CI may not have been initialized. */
267 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
269 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
271 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
273 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
274 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
276 pci
->pClientThreadInfo
= NULL
;
280 DPRINT1("No TEB for this Thread!\n");
281 // System thread running! Now SendMessage should be okay.
282 Win32Thread
->pcti
= &Win32Thread
->cti
;
284 Win32Thread
->pEThread
= Thread
;
289 PSINGLE_LIST_ENTRY e
;
291 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
293 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
294 pti
= Win32Thread
->ppi
->ptiList
;
295 if (pti
== Win32Thread
)
297 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
298 Win32Thread
->ppi
->cThreads
--;
304 if (pti
->ptiSibling
== Win32Thread
)
306 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
307 Win32Thread
->ppi
->cThreads
--;
310 pti
= pti
->ptiSibling
;
314 DceFreeThreadDCE(Win32Thread
);
315 HOOK_DestroyThreadHooks(Thread
);
316 EVENT_DestroyThreadEvents(Thread
);
318 DestroyTimersForThread(Win32Thread
);
319 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
320 UnregisterThreadHotKeys(Thread
);
321 /* what if this co_ func crash in umode? what will clean us up then? */
322 co_DestroyThreadWindows(Thread
);
323 IntBlockInput(Win32Thread
, FALSE
);
324 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
325 IntCleanupThreadCallbacks(Win32Thread
);
327 /* cleanup user object references stack */
328 e
= PopEntryList(&Win32Thread
->ReferencesList
);
331 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
332 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
333 UserDereferenceObject(ref
->obj
);
335 e
= PopEntryList(&Win32Thread
->ReferencesList
);
338 IntSetThreadDesktop(NULL
, TRUE
);
340 PsSetThreadWin32Thread(Thread
, NULL
);
343 RETURN( STATUS_SUCCESS
);
347 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
352 Win32kInitWin32Thread(PETHREAD Thread
)
356 Process
= Thread
->ThreadsProcess
;
358 if (Process
->Win32Process
== NULL
)
360 /* FIXME - lock the process */
361 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
363 if (Process
->Win32Process
== NULL
)
364 return STATUS_NO_MEMORY
;
366 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
367 /* FIXME - unlock the process */
369 Win32kProcessCallback(Process
, TRUE
);
372 if (Thread
->Tcb
.Win32Thread
== NULL
)
374 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
375 if (Thread
->Tcb
.Win32Thread
== NULL
)
376 return STATUS_NO_MEMORY
;
378 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
380 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
383 return(STATUS_SUCCESS
);
386 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
391 if (!NT_SUCCESS(Status)) \
393 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
398 * This definition doesn't work
404 IN PDRIVER_OBJECT DriverObject
,
405 IN PUNICODE_STRING RegistryPath
)
409 WIN32_CALLOUTS_FPNS CalloutData
= {0};
410 PVOID GlobalUserHeapBase
= NULL
;
413 * Register user mode call interface
414 * (system service table index = 1)
416 Result
= KeAddSystemServiceTable(Win32kSSDT
,
418 Win32kNumberOfSysCalls
,
423 DPRINT1("Adding system services failed!\n");
424 return STATUS_UNSUCCESSFUL
;
427 hModuleWin
= MmPageEntireDriver(DriverEntry
);
428 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
430 /* Register Object Manager Callbacks */
431 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
432 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
433 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
434 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
435 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
436 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
437 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
438 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
440 /* Register our per-process and per-thread structures. */
441 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
444 /* Register service hook callbacks */
445 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
446 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
449 /* Create the global USER heap */
450 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
452 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
453 if (GlobalUserHeap
== NULL
)
455 DPRINT1("Failed to initialize the global heap!\n");
456 return STATUS_UNSUCCESSFUL
;
459 /* Allocate global server info structure */
460 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
463 DPRINT1("Failed allocate server info structure!\n");
464 return STATUS_UNSUCCESSFUL
;
467 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
468 DPRINT("Global Server Data -> %x\n", gpsi
);
470 NT_ROF(InitGdiHandleTable());
471 NT_ROF(InitPaletteImpl());
473 /* Create stock objects, ie. precreated objects commonly
474 used by win32 applications */
475 CreateStockObjects();
476 CreateSysColorObjects();
478 NT_ROF(InitXlateImpl());
479 NT_ROF(InitPDEVImpl());
480 NT_ROF(InitLDEVImpl());
481 NT_ROF(InitDeviceImpl());
482 NT_ROF(InitDcImpl());
483 NT_ROF(InitUserImpl());
484 NT_ROF(InitHotkeyImpl());
485 NT_ROF(InitWindowStationImpl());
486 NT_ROF(InitDesktopImpl());
487 NT_ROF(InitWindowImpl());
488 NT_ROF(InitMenuImpl());
489 NT_ROF(InitInputImpl());
490 NT_ROF(InitKeyboardImpl());
491 NT_ROF(InitMonitorImpl());
492 NT_ROF(MsqInitializeImpl());
493 NT_ROF(InitTimerImpl());
494 NT_ROF(InitAcceleratorImpl());
495 NT_ROF(InitGuiCheckImpl());
497 /* Initialize FreeType library */
498 if (!InitFontSupport())
500 DPRINT1("Unable to initialize font support\n");
504 gusLanguageID
= IntGdiGetLanguageID();
506 return STATUS_SUCCESS
;