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.
26 PPROCESSINFO ppiScrnSaver
;
28 extern ULONG_PTR Win32kSSDT
[];
29 extern UCHAR Win32kSSPT
[];
30 extern ULONG Win32kNumberOfSysCalls
;
34 Win32kProcessCallback(struct _EPROCESS
*Process
,
37 PPROCESSINFO Win32Process
;
38 DECLARE_RETURN(NTSTATUS
);
40 DPRINT("Enter Win32kProcessCallback\n");
43 /* Get the Win32 Process */
44 Win32Process
= PsGetProcessWin32Process(Process
);
46 /* Allocate one if needed */
49 /* FIXME - lock the process */
50 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
54 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
56 RtlZeroMemory(Win32Process
, sizeof(PROCESSINFO
));
58 PsSetProcessWin32Process(Process
, Win32Process
);
59 /* FIXME - unlock the process */
66 PVOID UserBase
= NULL
;
67 PRTL_USER_PROCESS_PARAMETERS pParams
= NULL
;
69 extern PSECTION_OBJECT GlobalUserHeapSection
;
72 DbgInitDebugChannels();
75 TRACE_PPI(Win32Process
, UserProcess
,"Allocated ppi for PID:%d\n", Process
->UniqueProcessId
);
77 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
79 /* map the global heap into the process */
81 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
82 PsGetCurrentProcess(),
90 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
91 if (!NT_SUCCESS(Status
))
93 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
96 Win32Process
->HeapMappings
.Next
= NULL
;
97 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
98 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
99 Win32Process
->HeapMappings
.Count
= 1;
101 InitializeListHead(&Win32Process
->MenuListHead
);
103 InitializeListHead(&Win32Process
->GDIBrushAttrFreeList
);
104 InitializeListHead(&Win32Process
->GDIDcAttrFreeList
);
106 InitializeListHead(&Win32Process
->PrivateFontListHead
);
107 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
109 InitializeListHead(&Win32Process
->DriverObjListHead
);
110 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
112 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
113 EngCreateEvent((PEVENT
*)&Win32Process
->InputIdleEvent
);
114 KeInitializeEvent(Win32Process
->InputIdleEvent
, NotificationEvent
, FALSE
);
116 if(Process
->Peb
!= NULL
)
118 /* map the gdi handle table to user land */
119 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(Process
);
120 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
121 pParams
= Process
->Peb
->ProcessParameters
;
124 Win32Process
->peProcess
= Process
;
125 /* setup process flags */
126 Win32Process
->W32PF_flags
= W32PF_THREADCONNECTED
;
129 pParams
->WindowFlags
& STARTF_SCRNSAVER
)
131 ppiScrnSaver
= Win32Process
;
132 Win32Process
->W32PF_flags
|= W32PF_SCREENSAVER
;
135 /* Create pools for GDI object attributes */
136 Win32Process
->pPoolDcAttr
= GdiPoolCreate(sizeof(DC_ATTR
), 'acdG');
137 Win32Process
->pPoolBrushAttr
= GdiPoolCreate(sizeof(BRUSH_ATTR
), 'arbG');
138 Win32Process
->pPoolRgnAttr
= GdiPoolCreate(sizeof(RGN_ATTR
), 'agrG');
139 ASSERT(Win32Process
->pPoolDcAttr
);
140 ASSERT(Win32Process
->pPoolBrushAttr
);
141 ASSERT(Win32Process
->pPoolRgnAttr
);
145 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
146 Win32Process
->W32PF_flags
|= W32PF_TERMINATED
;
148 if (ppiScrnSaver
== Win32Process
) ppiScrnSaver
= NULL
;
150 /* Notify logon application to restart shell if needed */
151 if(Win32Process
->rpdeskStartup
->pDeskInfo
)
153 if(Win32Process
->rpdeskStartup
->pDeskInfo
->ppiShellProcess
== Win32Process
)
156 ExitCode
= PsGetProcessExitStatus(Win32Process
->peProcess
);
158 DPRINT1("Shell process is exiting (%d)\n", ExitCode
);
160 UserPostMessage(hwndSAS
,
167 if (Win32Process
->InputIdleEvent
)
169 EngFreeMem((PVOID
)Win32Process
->InputIdleEvent
);
170 Win32Process
->InputIdleEvent
= NULL
;
173 IntCleanupMenus(Process
, Win32Process
);
174 IntCleanupCurIcons(Process
, Win32Process
);
175 CleanupMonitorImpl();
177 /* no process windows should exist at this point, or the function will assert! */
178 DestroyProcessClasses(Win32Process
);
179 Win32Process
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
181 GDI_CleanupForProcess(Process
);
183 co_IntGraphicsCheck(FALSE
);
186 * Deregister logon application automatically
188 if(LogonProcess
== Win32Process
)
193 /* Close the startup desktop */
194 ASSERT(Win32Process
->rpdeskStartup
);
195 ASSERT(Win32Process
->hdeskStartup
);
196 ObDereferenceObject(Win32Process
->rpdeskStartup
);
197 ZwClose(Win32Process
->hdeskStartup
);
199 /* Close the current window station */
200 UserSetProcessWindowStation(NULL
);
202 /* Destroy GDI pools */
203 GdiPoolDestroy(Win32Process
->pPoolDcAttr
);
204 GdiPoolDestroy(Win32Process
->pPoolBrushAttr
);
205 GdiPoolDestroy(Win32Process
->pPoolRgnAttr
);
208 RETURN( STATUS_SUCCESS
);
212 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
219 Win32kThreadCallback(struct _ETHREAD
*Thread
,
220 PSW32THREADCALLOUTTYPE Type
)
222 struct _EPROCESS
*Process
;
223 PTHREADINFO Win32Thread
;
225 DECLARE_RETURN(NTSTATUS
);
227 DPRINT("Enter Win32kThreadCallback\n");
228 UserEnterExclusive();
230 Process
= Thread
->ThreadsProcess
;
232 /* Get the Win32 Thread */
233 Win32Thread
= PsGetThreadWin32Thread(Thread
);
235 /* Allocate one if needed */
238 /* FIXME - lock the process */
239 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
243 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
245 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
247 PsSetThreadWin32Thread(Thread
, Win32Thread
);
248 /* FIXME - unlock the process */
250 if (Type
== PsW32ThreadCalloutInitialize
)
252 HWINSTA hWinSta
= NULL
;
256 PUNICODE_STRING DesktopPath
;
258 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
260 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
262 InitializeListHead(&Win32Thread
->WindowListHead
);
263 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
264 InitializeListHead(&Win32Thread
->PtiLink
);
265 for (i
= 0; i
< NB_HOOKS
; i
++)
267 InitializeListHead(&Win32Thread
->aphkStart
[i
]);
270 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
271 co_IntDestroyCaret(Win32Thread
);
272 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
273 Win32Thread
->ptiSibling
= Win32Thread
->ppi
->ptiList
;
274 Win32Thread
->ppi
->ptiList
= Win32Thread
;
275 Win32Thread
->ppi
->cThreads
++;
276 if (Win32Thread
->rpdesk
&& !Win32Thread
->pDeskInfo
)
278 Win32Thread
->pDeskInfo
= Win32Thread
->rpdesk
->pDeskInfo
;
280 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
281 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
282 Win32Thread
->pEThread
= Thread
;
284 /* HAAAAAAAACK! This should go to Win32kProcessCallback */
285 if(Win32Thread
->ppi
->hdeskStartup
== NULL
)
288 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
289 * info structure. See documentation of CreateProcess()
291 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
292 Status
= IntParseDesktopPath(Process
,
296 if(NT_SUCCESS(Status
))
300 if(!UserSetProcessWindowStation(hWinSta
))
302 DPRINT1("Failed to set process window station\n");
308 /* Validate the new desktop. */
309 Status
= IntValidateDesktopHandle(hDesk
,
314 if(NT_SUCCESS(Status
))
316 Win32Thread
->ppi
->hdeskStartup
= hDesk
;
317 Win32Thread
->ppi
->rpdeskStartup
= pdesk
;
323 DPRINT1("No Desktop handle for this Thread!\n");
327 if (Win32Thread
->ppi
->hdeskStartup
!= NULL
)
329 if (!IntSetThreadDesktop(Win32Thread
->ppi
->hdeskStartup
, FALSE
))
331 DPRINT1("Unable to set thread desktop\n");
335 pTeb
= NtCurrentTeb();
337 { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
338 PCLIENTINFO pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
339 Win32Thread
->pClientInfo
= pci
;
340 pci
->ppi
= Win32Thread
->ppi
;
341 pci
->fsHooks
= Win32Thread
->fsHooks
;
342 if (Win32Thread
->KeyboardLayout
) pci
->hKL
= Win32Thread
->KeyboardLayout
->hkl
;
343 pci
->dwTIFlags
= Win32Thread
->TIF_flags
;
344 /* CI may not have been initialized. */
345 if (!pci
->pDeskInfo
&& Win32Thread
->pDeskInfo
)
347 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
349 pci
->pDeskInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pDeskInfo
- pci
->ulClientDelta
);
351 if (Win32Thread
->pcti
&& pci
->pDeskInfo
)
352 pci
->pClientThreadInfo
= (PVOID
)((ULONG_PTR
)Win32Thread
->pcti
- pci
->ulClientDelta
);
354 pci
->pClientThreadInfo
= NULL
;
358 DPRINT1("No TEB for this Thread!\n");
359 // System thread running! Now SendMessage should be okay.
360 Win32Thread
->pcti
= &Win32Thread
->cti
;
367 PSINGLE_LIST_ENTRY e
;
369 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
371 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
372 pti
= Win32Thread
->ppi
->ptiList
;
373 if (pti
== Win32Thread
)
375 Win32Thread
->ppi
->ptiList
= Win32Thread
->ptiSibling
;
376 Win32Thread
->ppi
->cThreads
--;
382 if (pti
->ptiSibling
== Win32Thread
)
384 pti
->ptiSibling
= Win32Thread
->ptiSibling
;
385 Win32Thread
->ppi
->cThreads
--;
388 pti
= pti
->ptiSibling
;
392 DceFreeThreadDCE(Win32Thread
);
393 HOOK_DestroyThreadHooks(Thread
);
394 EVENT_DestroyThreadEvents(Thread
);
396 DestroyTimersForThread(Win32Thread
);
397 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
398 UnregisterThreadHotKeys(Thread
);
399 /* what if this co_ func crash in umode? what will clean us up then? */
400 co_DestroyThreadWindows(Thread
);
401 IntBlockInput(Win32Thread
, FALSE
);
402 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
403 IntCleanupThreadCallbacks(Win32Thread
);
405 /* cleanup user object references stack */
406 e
= PopEntryList(&Win32Thread
->ReferencesList
);
409 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
410 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
411 UserDereferenceObject(ref
->obj
);
413 e
= PopEntryList(&Win32Thread
->ReferencesList
);
416 IntSetThreadDesktop(NULL
, TRUE
);
418 PsSetThreadWin32Thread(Thread
, NULL
);
421 RETURN( STATUS_SUCCESS
);
425 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
430 Win32kInitWin32Thread(PETHREAD Thread
)
434 Process
= Thread
->ThreadsProcess
;
436 if (Process
->Win32Process
== NULL
)
438 /* FIXME - lock the process */
439 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
441 if (Process
->Win32Process
== NULL
)
442 return STATUS_NO_MEMORY
;
444 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
445 /* FIXME - unlock the process */
447 Win32kProcessCallback(Process
, TRUE
);
450 if (Thread
->Tcb
.Win32Thread
== NULL
)
452 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
453 if (Thread
->Tcb
.Win32Thread
== NULL
)
454 return STATUS_NO_MEMORY
;
456 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
458 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
461 return(STATUS_SUCCESS
);
464 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
469 if (!NT_SUCCESS(Status)) \
471 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
476 * This definition doesn't work
482 IN PDRIVER_OBJECT DriverObject
,
483 IN PUNICODE_STRING RegistryPath
)
487 WIN32_CALLOUTS_FPNS CalloutData
= {0};
488 PVOID GlobalUserHeapBase
= NULL
;
491 * Register user mode call interface
492 * (system service table index = 1)
494 Result
= KeAddSystemServiceTable(Win32kSSDT
,
496 Win32kNumberOfSysCalls
,
501 DPRINT1("Adding system services failed!\n");
502 return STATUS_UNSUCCESSFUL
;
505 hModuleWin
= MmPageEntireDriver(DriverEntry
);
506 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
508 /* Register Object Manager Callbacks */
509 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
510 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
511 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
512 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
513 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
514 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
515 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
516 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
518 /* Register our per-process and per-thread structures. */
519 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
521 #if DBG_ENABLE_SERVICE_HOOKS
522 /* Register service hook callbacks */
523 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
524 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
527 /* Create the global USER heap */
528 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
530 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
531 if (GlobalUserHeap
== NULL
)
533 DPRINT1("Failed to initialize the global heap!\n");
534 return STATUS_UNSUCCESSFUL
;
537 /* Allocate global server info structure */
538 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
541 DPRINT1("Failed allocate server info structure!\n");
542 return STATUS_UNSUCCESSFUL
;
545 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
546 DPRINT("Global Server Data -> %x\n", gpsi
);
548 NT_ROF(InitGdiHandleTable());
549 NT_ROF(InitPaletteImpl());
551 /* Create stock objects, ie. precreated objects commonly
552 used by win32 applications */
553 CreateStockObjects();
554 CreateSysColorObjects();
556 NT_ROF(InitXlateImpl());
557 NT_ROF(InitPDEVImpl());
558 NT_ROF(InitLDEVImpl());
559 NT_ROF(InitDeviceImpl());
560 NT_ROF(InitDcImpl());
561 NT_ROF(InitUserImpl());
562 NT_ROF(InitHotkeyImpl());
563 NT_ROF(InitWindowStationImpl());
564 NT_ROF(InitDesktopImpl());
565 NT_ROF(InitWindowImpl());
566 NT_ROF(InitMenuImpl());
567 NT_ROF(InitInputImpl());
568 NT_ROF(InitKeyboardImpl());
569 NT_ROF(InitMonitorImpl());
570 NT_ROF(MsqInitializeImpl());
571 NT_ROF(InitTimerImpl());
572 NT_ROF(InitAcceleratorImpl());
573 NT_ROF(InitGuiCheckImpl());
575 /* Initialize FreeType library */
576 if (!InitFontSupport())
578 DPRINT1("Unable to initialize font support\n");
582 gusLanguageID
= IntGdiGetLanguageID();
584 return STATUS_SUCCESS
;