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;
118 /* Create pools for GDI object attributes */
119 Win32Process
->pPoolDcAttr
= GdiPoolCreate(sizeof(DC_ATTR
), 'acdG');
120 Win32Process
->pPoolBrushAttr
= GdiPoolCreate(sizeof(BRUSH_ATTR
), 'arbG');
121 Win32Process
->pPoolRgnAttr
= GdiPoolCreate(sizeof(RGN_ATTR
), 'agrG');
122 ASSERT(Win32Process
->pPoolDcAttr
);
123 ASSERT(Win32Process
->pPoolBrushAttr
);
124 ASSERT(Win32Process
->pPoolRgnAttr
);
128 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
129 Win32Process
->W32PF_flags
|= W32PF_TERMINATED
;
131 if (Win32Process
->InputIdleEvent
)
133 EngFreeMem((PVOID
)Win32Process
->InputIdleEvent
);
134 Win32Process
->InputIdleEvent
= NULL
;
137 IntCleanupMenus(Process
, Win32Process
);
138 IntCleanupCurIcons(Process
, Win32Process
);
139 CleanupMonitorImpl();
141 /* no process windows should exist at this point, or the function will assert! */
142 DestroyProcessClasses(Win32Process
);
143 Win32Process
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
145 GDI_CleanupForProcess(Process
);
147 co_IntGraphicsCheck(FALSE
);
150 * Deregister logon application automatically
152 if(LogonProcess
== Win32Process
)
157 /* Close the startup desktop */
158 ASSERT(Win32Process
->rpdeskStartup
);
159 ASSERT(Win32Process
->hdeskStartup
);
160 ObDereferenceObject(Win32Process
->rpdeskStartup
);
161 ZwClose(Win32Process
->hdeskStartup
);
163 /* Close the current window station */
164 UserSetProcessWindowStation(NULL
);
166 /* Destroy GDI pools */
167 GdiPoolDestroy(Win32Process
->pPoolDcAttr
);
168 GdiPoolDestroy(Win32Process
->pPoolBrushAttr
);
169 GdiPoolDestroy(Win32Process
->pPoolRgnAttr
);
172 RETURN( STATUS_SUCCESS
);
176 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
183 Win32kThreadCallback(struct _ETHREAD
*Thread
,
184 PSW32THREADCALLOUTTYPE Type
)
186 struct _EPROCESS
*Process
;
187 PTHREADINFO Win32Thread
;
189 DECLARE_RETURN(NTSTATUS
);
191 DPRINT("Enter Win32kThreadCallback\n");
192 UserEnterExclusive();
194 Process
= Thread
->ThreadsProcess
;
196 /* Get the Win32 Thread */
197 Win32Thread
= PsGetThreadWin32Thread(Thread
);
199 /* Allocate one if needed */
202 /* FIXME - lock the process */
203 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
207 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
209 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
211 PsSetThreadWin32Thread(Thread
, Win32Thread
);
212 /* FIXME - unlock the process */
214 if (Type
== PsW32ThreadCalloutInitialize
)
216 HWINSTA hWinSta
= NULL
;
220 PUNICODE_STRING DesktopPath
;
222 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
224 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
226 InitializeListHead(&Win32Thread
->WindowListHead
);
227 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
228 InitializeListHead(&Win32Thread
->PtiLink
);
229 for (i
= 0; i
< NB_HOOKS
; i
++)
231 InitializeListHead(&Win32Thread
->aphkStart
[i
]);
234 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
235 co_IntDestroyCaret(Win32Thread
);
236 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
237 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
238 Win32Thread
->ppi
->ptiList
= Win32Thread
;
239 Win32Thread
->ppi
->cThreads
++;
240 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
242 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
244 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
245 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
247 /* HAAAAAAAACK! This should go to Win32kProcessCallback */
248 if(Win32Thread
->ppi
->hdeskStartup
== NULL
)
251 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
252 * info structure. See documentation of CreateProcess()
254 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
255 Status
= IntParseDesktopPath(Process
,
259 if(NT_SUCCESS(Status
))
263 if(!UserSetProcessWindowStation(hWinSta
))
265 DPRINT1("Failed to set process window station\n");
271 /* Validate the new desktop. */
272 Status
= IntValidateDesktopHandle(hDesk
,
277 if(NT_SUCCESS(Status
))
279 Win32Thread
->ppi
->hdeskStartup
= hDesk
;
280 Win32Thread
->ppi
->rpdeskStartup
= pdesk
;
286 DPRINT1("No Desktop handle for this Thread!\n");
290 if (Win32Thread
->ppi
->hdeskStartup
!= NULL
)
292 if (!IntSetThreadDesktop(Win32Thread
->ppi
->hdeskStartup
, FALSE
))
294 DPRINT1("Unable to set thread desktop\n");
298 pTeb
= NtCurrentTeb();
300 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
301 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
302 Win32Thread
->pClientInfo
= pci
;
303 pci
->ppi
= Win32Thread
->ppi
;
304 pci
->fsHooks
= Win32Thread
->fsHooks
;
305 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
306 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
307 /* CI may not have been initialized. */
308 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
310 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
312 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
314 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
315 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
317 pci
->pClientThreadInfo
= NULL
;
321 DPRINT1("No TEB for this Thread!\n");
322 // System thread running! Now SendMessage should be okay.
323 Win32Thread
->pcti
= &Win32Thread
->cti
;
325 Win32Thread
->pEThread
= Thread
;
330 PSINGLE_LIST_ENTRY e
;
332 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
334 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
335 pti
= Win32Thread
->ppi
->ptiList
;
336 if (pti
== Win32Thread
)
338 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
339 Win32Thread
->ppi
->cThreads
--;
345 if (pti
->ptiSibling
== Win32Thread
)
347 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
348 Win32Thread
->ppi
->cThreads
--;
351 pti
= pti
->ptiSibling
;
355 DceFreeThreadDCE(Win32Thread
);
356 HOOK_DestroyThreadHooks(Thread
);
357 EVENT_DestroyThreadEvents(Thread
);
359 DestroyTimersForThread(Win32Thread
);
360 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
361 UnregisterThreadHotKeys(Thread
);
362 /* what if this co_ func crash in umode? what will clean us up then? */
363 co_DestroyThreadWindows(Thread
);
364 IntBlockInput(Win32Thread
, FALSE
);
365 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
366 IntCleanupThreadCallbacks(Win32Thread
);
368 /* cleanup user object references stack */
369 e
= PopEntryList(&Win32Thread
->ReferencesList
);
372 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
373 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
374 UserDereferenceObject(ref
->obj
);
376 e
= PopEntryList(&Win32Thread
->ReferencesList
);
379 IntSetThreadDesktop(NULL
, TRUE
);
381 PsSetThreadWin32Thread(Thread
, NULL
);
384 RETURN( STATUS_SUCCESS
);
388 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
393 Win32kInitWin32Thread(PETHREAD Thread
)
397 Process
= Thread
->ThreadsProcess
;
399 if (Process
->Win32Process
== NULL
)
401 /* FIXME - lock the process */
402 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
404 if (Process
->Win32Process
== NULL
)
405 return STATUS_NO_MEMORY
;
407 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
408 /* FIXME - unlock the process */
410 Win32kProcessCallback(Process
, TRUE
);
413 if (Thread
->Tcb
.Win32Thread
== NULL
)
415 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
416 if (Thread
->Tcb
.Win32Thread
== NULL
)
417 return STATUS_NO_MEMORY
;
419 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
421 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
424 return(STATUS_SUCCESS
);
427 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
432 if (!NT_SUCCESS(Status)) \
434 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
439 * This definition doesn't work
445 IN PDRIVER_OBJECT DriverObject
,
446 IN PUNICODE_STRING RegistryPath
)
450 WIN32_CALLOUTS_FPNS CalloutData
= {0};
451 PVOID GlobalUserHeapBase
= NULL
;
454 * Register user mode call interface
455 * (system service table index = 1)
457 Result
= KeAddSystemServiceTable(Win32kSSDT
,
459 Win32kNumberOfSysCalls
,
464 DPRINT1("Adding system services failed!\n");
465 return STATUS_UNSUCCESSFUL
;
468 hModuleWin
= MmPageEntireDriver(DriverEntry
);
469 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
471 /* Register Object Manager Callbacks */
472 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
473 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
474 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
475 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
476 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
477 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
478 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
479 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
481 /* Register our per-process and per-thread structures. */
482 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
484 #if DBG_ENABLE_SERVICE_HOOKS
485 /* Register service hook callbacks */
486 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
487 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
490 /* Create the global USER heap */
491 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
493 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
494 if (GlobalUserHeap
== NULL
)
496 DPRINT1("Failed to initialize the global heap!\n");
497 return STATUS_UNSUCCESSFUL
;
500 /* Allocate global server info structure */
501 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
504 DPRINT1("Failed allocate server info structure!\n");
505 return STATUS_UNSUCCESSFUL
;
508 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
509 DPRINT("Global Server Data -> %x\n", gpsi
);
511 NT_ROF(InitGdiHandleTable());
512 NT_ROF(InitPaletteImpl());
514 /* Create stock objects, ie. precreated objects commonly
515 used by win32 applications */
516 CreateStockObjects();
517 CreateSysColorObjects();
519 NT_ROF(InitXlateImpl());
520 NT_ROF(InitPDEVImpl());
521 NT_ROF(InitLDEVImpl());
522 NT_ROF(InitDeviceImpl());
523 NT_ROF(InitDcImpl());
524 NT_ROF(InitUserImpl());
525 NT_ROF(InitHotkeyImpl());
526 NT_ROF(InitWindowStationImpl());
527 NT_ROF(InitDesktopImpl());
528 NT_ROF(InitWindowImpl());
529 NT_ROF(InitMenuImpl());
530 NT_ROF(InitInputImpl());
531 NT_ROF(InitKeyboardImpl());
532 NT_ROF(InitMonitorImpl());
533 NT_ROF(MsqInitializeImpl());
534 NT_ROF(InitTimerImpl());
535 NT_ROF(InitAcceleratorImpl());
536 NT_ROF(InitGuiCheckImpl());
538 /* Initialize FreeType library */
539 if (!InitFontSupport())
541 DPRINT1("Unable to initialize font support\n");
545 gusLanguageID
= IntGdiGetLanguageID();
547 return STATUS_SUCCESS
;