2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * Entry Point for win32k.sys
24 #include <include/napi.h>
31 PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT
*SectionObject
);
32 BOOL INTERNAL_CALL
GDI_CleanupForProcess (struct _EPROCESS
*Process
);
34 PGDI_HANDLE_TABLE GdiHandleTable
= NULL
;
35 PSECTION_OBJECT GdiTableSection
= NULL
;
37 HANDLE GlobalUserHeap
= NULL
;
38 PSECTION_OBJECT GlobalUserHeapSection
= NULL
;
40 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
42 HSEMAPHORE hsemDriverMgmt
= NULL
;
46 extern ULONG_PTR Win32kSSDT
[];
47 extern UCHAR Win32kSSPT
[];
48 extern ULONG Win32kNumberOfSysCalls
;
52 Win32kProcessCallback(struct _EPROCESS
*Process
,
55 PPROCESSINFO Win32Process
;
56 DECLARE_RETURN(NTSTATUS
);
58 DPRINT("Enter Win32kProcessCallback\n");
61 /* Get the Win32 Process */
62 Win32Process
= PsGetProcessWin32Process(Process
);
64 /* Allocate one if needed */
67 /* FIXME - lock the process */
68 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
72 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
74 RtlZeroMemory(Win32Process
, sizeof(PROCESSINFO
));
76 PsSetProcessWin32Process(Process
, Win32Process
);
77 /* FIXME - unlock the process */
84 PVOID UserBase
= NULL
;
86 extern PSECTION_OBJECT GlobalUserHeapSection
;
87 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
89 /* map the global heap into the process */
91 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
92 PsGetCurrentProcess(),
100 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
106 Win32Process
->HeapMappings
.Next
= NULL
;
107 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
108 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
109 Win32Process
->HeapMappings
.Count
= 1;
111 InitializeListHead(&Win32Process
->ClassList
);
113 InitializeListHead(&Win32Process
->MenuListHead
);
115 InitializeListHead(&Win32Process
->GDIBrushAttrFreeList
);
116 InitializeListHead(&Win32Process
->GDIDcAttrFreeList
);
118 InitializeListHead(&Win32Process
->PrivateFontListHead
);
119 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
121 InitializeListHead(&Win32Process
->DriverObjListHead
);
122 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
124 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
126 if(Process
->Peb
!= NULL
)
128 /* map the gdi handle table to user land */
129 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
130 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
133 Win32Process
->peProcess
= Process
;
134 /* setup process flags */
135 Win32Process
->W32PF_flags
= 0;
139 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
140 IntCleanupMenus(Process
, Win32Process
);
141 IntCleanupCurIcons(Process
, Win32Process
);
142 CleanupMonitorImpl();
144 /* no process windows should exist at this point, or the function will assert! */
145 DestroyProcessClasses(Win32Process
);
147 GDI_CleanupForProcess(Process
);
149 co_IntGraphicsCheck(FALSE
);
152 * Deregister logon application automatically
154 if(LogonProcess
== Win32Process
)
160 RETURN( STATUS_SUCCESS
);
164 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
171 Win32kThreadCallback(struct _ETHREAD
*Thread
,
172 PSW32THREADCALLOUTTYPE Type
)
174 struct _EPROCESS
*Process
;
175 PTHREADINFO Win32Thread
;
176 DECLARE_RETURN(NTSTATUS
);
178 DPRINT("Enter Win32kThreadCallback\n");
179 UserEnterExclusive();
181 Process
= Thread
->ThreadsProcess
;
183 /* Get the Win32 Thread */
184 Win32Thread
= PsGetThreadWin32Thread(Thread
);
186 /* Allocate one if needed */
189 /* FIXME - lock the process */
190 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
194 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
196 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
198 PsSetThreadWin32Thread(Thread
, Win32Thread
);
199 /* FIXME - unlock the process */
201 if (Type
== PsW32ThreadCalloutInitialize
)
203 HWINSTA hWinSta
= NULL
;
207 PUNICODE_STRING DesktopPath
;
208 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
210 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
212 InitializeListHead(&Win32Thread
->WindowListHead
);
213 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
214 InitializeListHead(&Win32Thread
->PtiLink
);
217 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
218 * info structure. See documentation of CreateProcess()
220 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
221 Status
= IntParseDesktopPath(Process
,
225 if(NT_SUCCESS(Status
))
229 if(Process
!= CsrProcess
)
231 HWINSTA hProcessWinSta
= (HWINSTA
)InterlockedCompareExchangePointer((PVOID
)&Process
->Win32WindowStation
, (PVOID
)hWinSta
, NULL
);
232 if(hProcessWinSta
!= NULL
)
234 /* our process is already assigned to a different window station, we don't need the handle anymore */
246 PDESKTOP DesktopObject
;
247 Win32Thread
->rpdesk
= NULL
;
248 Status
= ObReferenceObjectByHandle(hDesk
,
252 (PVOID
*)&DesktopObject
,
255 if(NT_SUCCESS(Status
))
257 if (!IntSetThreadDesktop(DesktopObject
,
260 DPRINT1("Unable to set thread desktop\n");
265 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk
);
269 Win32Thread
->TIF_flags
&= ~TIF_INCLEANUP
;
270 co_IntDestroyCaret(Win32Thread
);
271 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
272 pTeb
= NtCurrentTeb();
275 Win32Thread
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
276 Win32Thread
->pClientInfo
->pClientThreadInfo
= NULL
;
278 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
279 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
280 Win32Thread
->pEThread
= Thread
;
284 PSINGLE_LIST_ENTRY e
;
286 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
288 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
289 DceFreeThreadDCE(Win32Thread
);
290 HOOK_DestroyThreadHooks(Thread
);
292 DestroyTimersForThread(Win32Thread
);
293 KeSetEvent(Win32Thread
->MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
294 UnregisterThreadHotKeys(Thread
);
295 /* what if this co_ func crash in umode? what will clean us up then? */
296 co_DestroyThreadWindows(Thread
);
297 IntBlockInput(Win32Thread
, FALSE
);
298 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
299 IntCleanupThreadCallbacks(Win32Thread
);
301 /* cleanup user object references stack */
302 e
= PopEntryList(&Win32Thread
->ReferencesList
);
305 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
306 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
307 UserDereferenceObject(ref
->obj
);
309 e
= PopEntryList(&Win32Thread
->ReferencesList
);
312 IntSetThreadDesktop(NULL
,
315 PsSetThreadWin32Thread(Thread
, NULL
);
318 RETURN( STATUS_SUCCESS
);
322 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
326 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
327 not called there anymore, please delete */
329 Win32kInitWin32Thread(PETHREAD Thread
)
333 Process
= Thread
->ThreadsProcess
;
335 if (Process
->Win32Process
== NULL
)
337 /* FIXME - lock the process */
338 Process
->Win32Process
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PROCESSINFO
), USERTAG_PROCESSINFO
);
340 if (Process
->Win32Process
== NULL
)
341 return STATUS_NO_MEMORY
;
343 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
344 /* FIXME - unlock the process */
346 Win32kProcessCallback(Process
, TRUE
);
349 if (Thread
->Tcb
.Win32Thread
== NULL
)
351 Thread
->Tcb
.Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(THREADINFO
), USERTAG_THREADINFO
);
352 if (Thread
->Tcb
.Win32Thread
== NULL
)
353 return STATUS_NO_MEMORY
;
355 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
357 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
360 return(STATUS_SUCCESS
);
363 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
366 * This definition doesn't work
370 IN PDRIVER_OBJECT DriverObject
,
371 IN PUNICODE_STRING RegistryPath
)
375 WIN32_CALLOUTS_FPNS CalloutData
= {0};
376 PVOID GlobalUserHeapBase
= NULL
;
379 * Register user mode call interface
380 * (system service table index = 1)
382 Result
= KeAddSystemServiceTable (Win32kSSDT
,
384 Win32kNumberOfSysCalls
,
389 DPRINT1("Adding system services failed!\n");
390 return STATUS_UNSUCCESSFUL
;
393 hModuleWin
= MmPageEntireDriver(DriverEntry
);
394 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
396 * Register Object Manager Callbacks
398 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
399 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
400 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
401 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
402 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
403 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
406 * Register our per-process and per-thread structures.
408 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
410 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
412 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
413 if (GlobalUserHeap
== NULL
)
415 DPRINT1("Failed to initialize the global heap!\n");
416 return STATUS_UNSUCCESSFUL
;
421 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
424 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
425 DPRINT("Global Server Data -> %x\n", gpsi
);
433 if(!hsemDriverMgmt
) hsemDriverMgmt
= EngCreateSemaphore();
435 GdiHandleTable
= GDIOBJ_iAllocHandleTable(&GdiTableSection
);
436 if (GdiHandleTable
== NULL
)
438 DPRINT1("Failed to initialize the GDI handle table.\n");
439 return STATUS_UNSUCCESSFUL
;
442 /* Initialize default palettes */
445 /* Create stock objects, ie. precreated objects commonly
446 used by win32 applications */
447 CreateStockObjects();
448 CreateSysColorObjects();
455 Status
= InitDcImpl();
456 if (!NT_SUCCESS(Status
))
458 DPRINT1("Failed to initialize Device context implementation!\n");
459 return STATUS_UNSUCCESSFUL
;
462 Status
= InitUserImpl();
463 if (!NT_SUCCESS(Status
))
465 DPRINT1("Failed to initialize user implementation!\n");
466 return STATUS_UNSUCCESSFUL
;
469 Status
= InitHotkeyImpl();
470 if (!NT_SUCCESS(Status
))
472 DPRINT1("Failed to initialize hotkey implementation!\n");
473 return STATUS_UNSUCCESSFUL
;
476 Status
= InitWindowStationImpl();
477 if (!NT_SUCCESS(Status
))
479 DPRINT1("Failed to initialize window station implementation!\n");
480 return STATUS_UNSUCCESSFUL
;
483 Status
= InitDesktopImpl();
484 if (!NT_SUCCESS(Status
))
486 DPRINT1("Failed to initialize desktop implementation!\n");
487 return STATUS_UNSUCCESSFUL
;
490 Status
= InitWindowImpl();
491 if (!NT_SUCCESS(Status
))
493 DPRINT1("Failed to initialize window implementation!\n");
494 return STATUS_UNSUCCESSFUL
;
497 Status
= InitMenuImpl();
498 if (!NT_SUCCESS(Status
))
500 DPRINT1("Failed to initialize menu implementation!\n");
501 return STATUS_UNSUCCESSFUL
;
504 Status
= InitInputImpl();
505 if (!NT_SUCCESS(Status
))
507 DPRINT1("Failed to initialize input implementation.\n");
511 Status
= InitKeyboardImpl();
512 if (!NT_SUCCESS(Status
))
514 DPRINT1("Failed to initialize keyboard implementation.\n");
518 Status
= InitMonitorImpl();
519 if (!NT_SUCCESS(Status
))
521 DbgPrint("Failed to initialize monitor implementation!\n");
522 return STATUS_UNSUCCESSFUL
;
525 Status
= MsqInitializeImpl();
526 if (!NT_SUCCESS(Status
))
528 DPRINT1("Failed to initialize message queue implementation.\n");
532 Status
= InitTimerImpl();
533 if (!NT_SUCCESS(Status
))
535 DPRINT1("Failed to initialize timer implementation.\n");
539 Status
= InitAcceleratorImpl();
540 if (!NT_SUCCESS(Status
))
542 DPRINT1("Failed to initialize accelerator implementation.\n");
546 Status
= InitGuiCheckImpl();
547 if (!NT_SUCCESS(Status
))
549 DPRINT1("Failed to initialize GUI check implementation.\n");
553 /* Initialize FreeType library */
554 if (! InitFontSupport())
556 DPRINT1("Unable to initialize font support\n");
557 return STATUS_UNSUCCESSFUL
;
560 gusLanguageID
= IntGdiGetLanguageID();
562 return STATUS_SUCCESS
;