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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 LIST_ENTRY GlobalDriverListHead
;
39 HANDLE GlobalUserHeap
= NULL
;
40 PSECTION_OBJECT GlobalUserHeapSection
= NULL
;
42 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
44 HSEMAPHORE hsemDriverMgmt
= NULL
;
48 extern ULONG_PTR Win32kSSDT
[];
49 extern UCHAR Win32kSSPT
[];
50 extern ULONG Win32kNumberOfSysCalls
;
54 Win32kProcessCallback(struct _EPROCESS
*Process
,
57 PPROCESSINFO Win32Process
;
58 DECLARE_RETURN(NTSTATUS
);
60 DPRINT("Enter Win32kProcessCallback\n");
63 /* Get the Win32 Process */
64 Win32Process
= PsGetProcessWin32Process(Process
);
66 /* Allocate one if needed */
69 /* FIXME - lock the process */
70 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
74 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
76 RtlZeroMemory(Win32Process
, sizeof(PROCESSINFO
));
78 PsSetProcessWin32Process(Process
, Win32Process
);
79 /* FIXME - unlock the process */
86 PVOID UserBase
= NULL
;
88 extern PSECTION_OBJECT GlobalUserHeapSection
;
89 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
91 /* map the global heap into the process */
93 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
94 PsGetCurrentProcess(),
102 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
103 if (!NT_SUCCESS(Status
))
105 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
108 Win32Process
->HeapMappings
.Next
= NULL
;
109 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
110 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
111 Win32Process
->HeapMappings
.Count
= 1;
113 InitializeListHead(&Win32Process
->ClassList
);
115 InitializeListHead(&Win32Process
->MenuListHead
);
117 InitializeListHead(&Win32Process
->PrivateFontListHead
);
118 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
120 InitializeListHead(&Win32Process
->DriverObjListHead
);
121 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
123 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
125 if(Process
->Peb
!= NULL
)
127 /* map the gdi handle table to user land */
128 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
129 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
132 /* setup process flags */
133 Win32Process
->W32PF_flags
= 0;
137 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
138 IntCleanupMenus(Process
, Win32Process
);
139 IntCleanupCurIcons(Process
, Win32Process
);
140 CleanupMonitorImpl();
142 /* no process windows should exist at this point, or the function will assert! */
143 DestroyProcessClasses(Win32Process
);
145 GDI_CleanupForProcess(Process
);
147 co_IntGraphicsCheck(FALSE
);
150 * Deregister logon application automatically
152 if(LogonProcess
== Win32Process
)
158 RETURN( STATUS_SUCCESS
);
162 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
169 Win32kThreadCallback(struct _ETHREAD
*Thread
,
170 PSW32THREADCALLOUTTYPE Type
)
172 struct _EPROCESS
*Process
;
173 PTHREADINFO Win32Thread
;
174 DECLARE_RETURN(NTSTATUS
);
176 DPRINT("Enter Win32kThreadCallback\n");
177 UserEnterExclusive();
179 Process
= Thread
->ThreadsProcess
;
181 /* Get the Win32 Thread */
182 Win32Thread
= PsGetThreadWin32Thread(Thread
);
184 /* Allocate one if needed */
187 /* FIXME - lock the process */
188 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
192 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
194 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
196 PsSetThreadWin32Thread(Thread
, Win32Thread
);
197 /* FIXME - unlock the process */
199 if (Type
== PsW32ThreadCalloutInitialize
)
201 HWINSTA hWinSta
= NULL
;
205 PUNICODE_STRING DesktopPath
;
206 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
208 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
210 InitializeListHead(&Win32Thread
->WindowListHead
);
211 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
212 InitializeListHead(&Win32Thread
->PtiLink
);
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(Process
!= CsrProcess
)
229 HWINSTA hProcessWinSta
= (HWINSTA
)InterlockedCompareExchangePointer((PVOID
)&Process
->Win32WindowStation
, (PVOID
)hWinSta
, NULL
);
230 if(hProcessWinSta
!= NULL
)
232 /* our process is already assigned to a different window station, we don't need the handle anymore */
244 PDESKTOP DesktopObject
;
245 Win32Thread
->Desktop
= NULL
;
246 Status
= ObReferenceObjectByHandle(hDesk
,
250 (PVOID
*)&DesktopObject
,
253 if(NT_SUCCESS(Status
))
255 if (!IntSetThreadDesktop(DesktopObject
,
258 DPRINT1("Unable to set thread desktop\n");
263 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk
);
267 Win32Thread
->IsExiting
= FALSE
;
268 co_IntDestroyCaret(Win32Thread
);
269 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
270 pTeb
= NtCurrentTeb();
273 Win32Thread
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
274 Win32Thread
->pClientInfo
->pClientThreadInfo
= NULL
;
276 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
277 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
278 Win32Thread
->pEThread
= Thread
;
282 PSINGLE_LIST_ENTRY e
;
284 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
286 Win32Thread
->IsExiting
= TRUE
;
287 Win32Thread
->TIF_flags
|= TIF_INCLEANUP
;
288 HOOK_DestroyThreadHooks(Thread
);
289 UnregisterThreadHotKeys(Thread
);
290 /* what if this co_ func crash in umode? what will clean us up then? */
291 co_DestroyThreadWindows(Thread
);
292 IntBlockInput(Win32Thread
, FALSE
);
293 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
294 IntCleanupThreadCallbacks(Win32Thread
);
296 /* cleanup user object references stack */
297 e
= PopEntryList(&Win32Thread
->ReferencesList
);
300 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
301 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
302 UserDereferenceObject(ref
->obj
);
304 e
= PopEntryList(&Win32Thread
->ReferencesList
);
307 IntSetThreadDesktop(NULL
,
310 PsSetThreadWin32Thread(Thread
, NULL
);
313 RETURN( STATUS_SUCCESS
);
317 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
321 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
322 not called there anymore, please delete */
324 Win32kInitWin32Thread(PETHREAD Thread
)
328 Process
= Thread
->ThreadsProcess
;
330 if (Process
->Win32Process
== NULL
)
332 /* FIXME - lock the process */
333 Process
->Win32Process
= ExAllocatePool(NonPagedPool
, sizeof(PROCESSINFO
));
335 if (Process
->Win32Process
== NULL
)
336 return STATUS_NO_MEMORY
;
338 RtlZeroMemory(Process
->Win32Process
, sizeof(PROCESSINFO
));
339 /* FIXME - unlock the process */
341 Win32kProcessCallback(Process
, TRUE
);
344 if (Thread
->Tcb
.Win32Thread
== NULL
)
346 Thread
->Tcb
.Win32Thread
= ExAllocatePool (NonPagedPool
, sizeof(THREADINFO
));
347 if (Thread
->Tcb
.Win32Thread
== NULL
)
348 return STATUS_NO_MEMORY
;
350 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
352 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
355 return(STATUS_SUCCESS
);
360 * This definition doesn't work
364 IN PDRIVER_OBJECT DriverObject
,
365 IN PUNICODE_STRING RegistryPath
)
369 WIN32_CALLOUTS_FPNS CalloutData
= {0};
370 PVOID GlobalUserHeapBase
= NULL
;
373 * Register user mode call interface
374 * (system service table index = 1)
376 Result
= KeAddSystemServiceTable (Win32kSSDT
,
378 Win32kNumberOfSysCalls
,
383 DPRINT1("Adding system services failed!\n");
384 return STATUS_UNSUCCESSFUL
;
387 hModuleWin
= MmPageEntireDriver(DriverEntry
);
388 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin
);
390 * Register Object Manager Callbacks
392 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
393 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
394 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
395 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
396 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
397 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
400 * Register our per-process and per-thread structures.
402 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
404 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
406 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
407 if (GlobalUserHeap
== NULL
)
409 DPRINT1("Failed to initialize the global heap!\n");
410 return STATUS_UNSUCCESSFUL
;
413 /* Initialize a list of loaded drivers in Win32 subsystem */
414 InitializeListHead(&GlobalDriverListHead
);
416 if(!hsemDriverMgmt
) hsemDriverMgmt
= EngCreateSemaphore();
418 GdiHandleTable
= GDIOBJ_iAllocHandleTable(&GdiTableSection
);
419 if (GdiHandleTable
== NULL
)
421 DPRINT1("Failed to initialize the GDI handle table.\n");
422 return STATUS_UNSUCCESSFUL
;
425 Status
= InitUserImpl();
426 if (!NT_SUCCESS(Status
))
428 DPRINT1("Failed to initialize user implementation!\n");
429 return STATUS_UNSUCCESSFUL
;
432 Status
= InitHotkeyImpl();
433 if (!NT_SUCCESS(Status
))
435 DPRINT1("Failed to initialize hotkey implementation!\n");
436 return STATUS_UNSUCCESSFUL
;
439 Status
= InitWindowStationImpl();
440 if (!NT_SUCCESS(Status
))
442 DPRINT1("Failed to initialize window station implementation!\n");
443 return STATUS_UNSUCCESSFUL
;
446 Status
= InitDesktopImpl();
447 if (!NT_SUCCESS(Status
))
449 DPRINT1("Failed to initialize desktop implementation!\n");
450 return STATUS_UNSUCCESSFUL
;
453 Status
= InitWindowImpl();
454 if (!NT_SUCCESS(Status
))
456 DPRINT1("Failed to initialize window implementation!\n");
457 return STATUS_UNSUCCESSFUL
;
460 Status
= InitMenuImpl();
461 if (!NT_SUCCESS(Status
))
463 DPRINT1("Failed to initialize menu implementation!\n");
464 return STATUS_UNSUCCESSFUL
;
467 Status
= InitInputImpl();
468 if (!NT_SUCCESS(Status
))
470 DPRINT1("Failed to initialize input implementation.\n");
474 Status
= InitKeyboardImpl();
475 if (!NT_SUCCESS(Status
))
477 DPRINT1("Failed to initialize keyboard implementation.\n");
481 Status
= InitMonitorImpl();
482 if (!NT_SUCCESS(Status
))
484 DbgPrint("Failed to initialize monitor implementation!\n");
485 return STATUS_UNSUCCESSFUL
;
488 Status
= MsqInitializeImpl();
489 if (!NT_SUCCESS(Status
))
491 DPRINT1("Failed to initialize message queue implementation.\n");
495 Status
= InitTimerImpl();
496 if (!NT_SUCCESS(Status
))
498 DPRINT1("Failed to initialize timer implementation.\n");
502 Status
= InitAcceleratorImpl();
503 if (!NT_SUCCESS(Status
))
505 DPRINT1("Failed to initialize accelerator implementation.\n");
509 Status
= InitGuiCheckImpl();
510 if (!NT_SUCCESS(Status
))
512 DPRINT1("Failed to initialize GUI check implementation.\n");
516 Status
= InitDcImpl();
517 if (!NT_SUCCESS(Status
))
519 DPRINT1("Failed to initialize Device context implementation!\n");
520 return STATUS_UNSUCCESSFUL
;
523 /* Initialize FreeType library */
524 if (! InitFontSupport())
526 DPRINT1("Unable to initialize font support\n");
527 return STATUS_UNSUCCESSFUL
;
532 /* Create stock objects, ie. precreated objects commonly
533 used by win32 applications */
534 CreateStockObjects();
535 CreateSysColorObjects();
537 gusLanguageID
= IntGdiGetLanguageID();
539 return STATUS_SUCCESS
;