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.
21 * Entry Point for win32k.sys
25 #include <include/napi.h>
30 PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT
*SectionObject
);
31 BOOL INTERNAL_CALL
GDI_CleanupForProcess (struct _EPROCESS
*Process
);
33 PGDI_HANDLE_TABLE GdiHandleTable
= NULL
;
34 PSECTION_OBJECT GdiTableSection
= NULL
;
36 LIST_ENTRY GlobalDriverListHead
;
38 HANDLE GlobalUserHeap
= NULL
;
39 PSECTION_OBJECT GlobalUserHeapSection
= NULL
;
41 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
43 HSEMAPHORE hsemDriverMgmt
= NULL
;
47 extern ULONG_PTR Win32kSSDT
[];
48 extern UCHAR Win32kSSPT
[];
49 extern ULONG Win32kNumberOfSysCalls
;
53 Win32kProcessCallback(struct _EPROCESS
*Process
,
56 PW32PROCESS Win32Process
;
57 DECLARE_RETURN(NTSTATUS
);
59 DPRINT("Enter Win32kProcessCallback\n");
62 /* Get the Win32 Process */
63 Win32Process
= PsGetProcessWin32Process(Process
);
65 /* Allocate one if needed */
68 /* FIXME - lock the process */
69 Win32Process
= ExAllocatePoolWithTag(NonPagedPool
,
71 TAG('W', '3', '2', 'p'));
73 if (Win32Process
== NULL
) RETURN( STATUS_NO_MEMORY
);
75 RtlZeroMemory(Win32Process
, sizeof(W32PROCESS
));
77 PsSetProcessWin32Process(Process
, Win32Process
);
78 /* FIXME - unlock the process */
85 PVOID UserBase
= NULL
;
87 extern PSECTION_OBJECT GlobalUserHeapSection
;
88 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
90 /* map the global heap into the process */
92 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
93 PsGetCurrentProcess(),
101 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
102 if (!NT_SUCCESS(Status
))
104 DPRINT1("Failed to map the global heap! 0x%x\n", Status
);
107 Win32Process
->HeapMappings
.Next
= NULL
;
108 Win32Process
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
109 Win32Process
->HeapMappings
.UserMapping
= UserBase
;
110 Win32Process
->HeapMappings
.Count
= 1;
112 InitializeListHead(&Win32Process
->ClassList
);
114 InitializeListHead(&Win32Process
->MenuListHead
);
116 InitializeListHead(&Win32Process
->PrivateFontListHead
);
117 ExInitializeFastMutex(&Win32Process
->PrivateFontListLock
);
119 InitializeListHead(&Win32Process
->DriverObjListHead
);
120 ExInitializeFastMutex(&Win32Process
->DriverObjListLock
);
122 Win32Process
->KeyboardLayout
= W32kGetDefaultKeyLayout();
124 if(Process
->Peb
!= NULL
)
126 /* map the gdi handle table to user land */
127 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(GdiTableSection
, Process
);
128 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
131 /* setup process flags */
132 Win32Process
->W32PF_flags
= 0;
136 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process
->UniqueProcessId
, KeGetCurrentIrql());
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
);
144 GDI_CleanupForProcess(Process
);
146 co_IntGraphicsCheck(FALSE
);
149 * Deregister logon application automatically
151 if(LogonProcess
== Win32Process
)
156 if (Win32Process
->ProcessInfo
!= NULL
)
158 UserHeapFree(Win32Process
->ProcessInfo
);
159 Win32Process
->ProcessInfo
= NULL
;
163 RETURN( STATUS_SUCCESS
);
167 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_
);
174 Win32kThreadCallback(struct _ETHREAD
*Thread
,
175 PSW32THREADCALLOUTTYPE Type
)
177 struct _EPROCESS
*Process
;
178 PTHREADINFO Win32Thread
;
179 DECLARE_RETURN(NTSTATUS
);
181 DPRINT("Enter Win32kThreadCallback\n");
182 UserEnterExclusive();
184 Process
= Thread
->ThreadsProcess
;
186 /* Get the Win32 Thread */
187 Win32Thread
= PsGetThreadWin32Thread(Thread
);
189 /* Allocate one if needed */
192 /* FIXME - lock the process */
193 Win32Thread
= ExAllocatePoolWithTag(NonPagedPool
,
195 TAG('W', '3', '2', 't'));
197 if (Win32Thread
== NULL
) RETURN( STATUS_NO_MEMORY
);
199 RtlZeroMemory(Win32Thread
, sizeof(THREADINFO
));
201 PsSetThreadWin32Thread(Thread
, Win32Thread
);
202 /* FIXME - unlock the process */
204 if (Type
== PsW32ThreadCalloutInitialize
)
206 HWINSTA hWinSta
= NULL
;
210 PUNICODE_STRING DesktopPath
;
211 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= (Process
->Peb
? Process
->Peb
->ProcessParameters
: NULL
);
213 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
215 InitializeListHead(&Win32Thread
->WindowListHead
);
216 InitializeListHead(&Win32Thread
->W32CallbackListHead
);
217 InitializeListHead(&Win32Thread
->PtiLink
);
220 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
221 * info structure. See documentation of CreateProcess()
223 DesktopPath
= (ProcessParams
? ((ProcessParams
->DesktopInfo
.Length
> 0) ? &ProcessParams
->DesktopInfo
: NULL
) : NULL
);
224 Status
= IntParseDesktopPath(Process
,
228 if(NT_SUCCESS(Status
))
232 if(Process
!= CsrProcess
)
234 HWINSTA hProcessWinSta
= (HWINSTA
)InterlockedCompareExchangePointer((PVOID
)&Process
->Win32WindowStation
, (PVOID
)hWinSta
, NULL
);
235 if(hProcessWinSta
!= NULL
)
237 /* our process is already assigned to a different window station, we don't need the handle anymore */
249 PDESKTOP DesktopObject
;
250 Win32Thread
->Desktop
= NULL
;
251 Status
= ObReferenceObjectByHandle(hDesk
,
255 (PVOID
*)&DesktopObject
,
258 if(NT_SUCCESS(Status
))
260 if (!IntSetThreadDesktop(DesktopObject
,
263 DPRINT1("Unable to set thread desktop\n");
268 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk
);
272 Win32Thread
->IsExiting
= FALSE
;
273 co_IntDestroyCaret(Win32Thread
);
274 Win32Thread
->ppi
= PsGetCurrentProcessWin32Process();
275 pTeb
= NtCurrentTeb();
278 Win32Thread
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
279 Win32Thread
->pClientInfo
->pClientThreadInfo
= NULL
;
281 Win32Thread
->MessageQueue
= MsqCreateMessageQueue(Thread
);
282 Win32Thread
->KeyboardLayout
= W32kGetDefaultKeyLayout();
283 if (Win32Thread
->ThreadInfo
)
285 Win32Thread
->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
= 0;
286 // Win32Thread->pClientInfo->pClientThreadInfo = &Win32Thread->ThreadInfo->ClientThreadInfo;
291 PSINGLE_LIST_ENTRY e
;
293 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread
->Cid
.UniqueThread
, KeGetCurrentIrql());
295 Win32Thread
->IsExiting
= TRUE
;
296 HOOK_DestroyThreadHooks(Thread
);
297 UnregisterThreadHotKeys(Thread
);
298 /* what if this co_ func crash in umode? what will clean us up then? */
299 co_DestroyThreadWindows(Thread
);
300 IntBlockInput(Win32Thread
, FALSE
);
301 MsqDestroyMessageQueue(Win32Thread
->MessageQueue
);
302 IntCleanupThreadCallbacks(Win32Thread
);
304 /* cleanup user object references stack */
305 e
= PopEntryList(&Win32Thread
->ReferencesList
);
308 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(e
, USER_REFERENCE_ENTRY
, Entry
);
309 DPRINT("thread clean: remove reference obj 0x%x\n",ref
->obj
);
310 UserDereferenceObject(ref
->obj
);
312 e
= PopEntryList(&Win32Thread
->ReferencesList
);
315 IntSetThreadDesktop(NULL
,
318 if (Win32Thread
->ThreadInfo
!= NULL
)
320 UserHeapFree(Win32Thread
->ThreadInfo
);
321 Win32Thread
->ThreadInfo
= NULL
;
324 PsSetThreadWin32Thread(Thread
, NULL
);
327 RETURN( STATUS_SUCCESS
);
331 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_
);
335 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
336 not called there anymore, please delete */
338 Win32kInitWin32Thread(PETHREAD Thread
)
342 Process
= Thread
->ThreadsProcess
;
344 if (Process
->Win32Process
== NULL
)
346 /* FIXME - lock the process */
347 Process
->Win32Process
= ExAllocatePool(NonPagedPool
, sizeof(W32PROCESS
));
349 if (Process
->Win32Process
== NULL
)
350 return STATUS_NO_MEMORY
;
352 RtlZeroMemory(Process
->Win32Process
, sizeof(W32PROCESS
));
353 /* FIXME - unlock the process */
355 Win32kProcessCallback(Process
, TRUE
);
358 if (Thread
->Tcb
.Win32Thread
== NULL
)
360 Thread
->Tcb
.Win32Thread
= ExAllocatePool (NonPagedPool
, sizeof(THREADINFO
));
361 if (Thread
->Tcb
.Win32Thread
== NULL
)
362 return STATUS_NO_MEMORY
;
364 RtlZeroMemory(Thread
->Tcb
.Win32Thread
, sizeof(THREADINFO
));
366 Win32kThreadCallback(Thread
, PsW32ThreadCalloutInitialize
);
369 return(STATUS_SUCCESS
);
374 * This definition doesn't work
378 IN PDRIVER_OBJECT DriverObject
,
379 IN PUNICODE_STRING RegistryPath
)
383 WIN32_CALLOUTS_FPNS CalloutData
= {0};
384 PVOID GlobalUserHeapBase
= NULL
;
387 * Register user mode call interface
388 * (system service table index = 1)
390 Result
= KeAddSystemServiceTable (Win32kSSDT
,
392 Win32kNumberOfSysCalls
,
397 DPRINT1("Adding system services failed!\n");
398 return STATUS_UNSUCCESSFUL
;
402 * Register Object Manager Callbacks
404 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
405 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
406 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
407 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
408 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
409 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
412 * Register our per-process and per-thread structures.
414 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
416 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
418 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
419 if (GlobalUserHeap
== NULL
)
421 DPRINT1("Failed to initialize the global heap!\n");
422 return STATUS_UNSUCCESSFUL
;
425 /* Initialize a list of loaded drivers in Win32 subsystem */
426 InitializeListHead(&GlobalDriverListHead
);
428 if(!hsemDriverMgmt
) hsemDriverMgmt
= EngCreateSemaphore();
430 GdiHandleTable
= GDIOBJ_iAllocHandleTable(&GdiTableSection
);
431 if (GdiHandleTable
== NULL
)
433 DPRINT1("Failed to initialize the GDI handle table.\n");
434 return STATUS_UNSUCCESSFUL
;
437 Status
= InitUserImpl();
438 if (!NT_SUCCESS(Status
))
440 DPRINT1("Failed to initialize user implementation!\n");
441 return STATUS_UNSUCCESSFUL
;
444 Status
= InitHotkeyImpl();
445 if (!NT_SUCCESS(Status
))
447 DPRINT1("Failed to initialize hotkey implementation!\n");
448 return STATUS_UNSUCCESSFUL
;
451 Status
= InitWindowStationImpl();
452 if (!NT_SUCCESS(Status
))
454 DPRINT1("Failed to initialize window station implementation!\n");
455 return STATUS_UNSUCCESSFUL
;
458 Status
= InitDesktopImpl();
459 if (!NT_SUCCESS(Status
))
461 DPRINT1("Failed to initialize desktop implementation!\n");
462 return STATUS_UNSUCCESSFUL
;
465 Status
= InitWindowImpl();
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("Failed to initialize window implementation!\n");
469 return STATUS_UNSUCCESSFUL
;
472 Status
= InitMenuImpl();
473 if (!NT_SUCCESS(Status
))
475 DPRINT1("Failed to initialize menu implementation!\n");
476 return STATUS_UNSUCCESSFUL
;
479 Status
= InitInputImpl();
480 if (!NT_SUCCESS(Status
))
482 DPRINT1("Failed to initialize input implementation.\n");
486 Status
= InitKeyboardImpl();
487 if (!NT_SUCCESS(Status
))
489 DPRINT1("Failed to initialize keyboard implementation.\n");
493 Status
= InitMonitorImpl();
494 if (!NT_SUCCESS(Status
))
496 DbgPrint("Failed to initialize monitor implementation!\n");
497 return STATUS_UNSUCCESSFUL
;
500 Status
= MsqInitializeImpl();
501 if (!NT_SUCCESS(Status
))
503 DPRINT1("Failed to initialize message queue implementation.\n");
507 Status
= InitTimerImpl();
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("Failed to initialize timer implementation.\n");
514 Status
= InitAcceleratorImpl();
515 if (!NT_SUCCESS(Status
))
517 DPRINT1("Failed to initialize accelerator implementation.\n");
521 Status
= InitGuiCheckImpl();
522 if (!NT_SUCCESS(Status
))
524 DPRINT1("Failed to initialize GUI check implementation.\n");
528 Status
= InitDcImpl();
529 if (!NT_SUCCESS(Status
))
531 DPRINT1("Failed to initialize Device context implementation!\n");
532 return STATUS_UNSUCCESSFUL
;
535 /* Initialize FreeType library */
536 if (! InitFontSupport())
538 DPRINT1("Unable to initialize font support\n");
539 return STATUS_UNSUCCESSFUL
;
542 /* Create stock objects, ie. precreated objects commonly
543 used by win32 applications */
544 CreateStockObjects();
545 CreateSysColorObjects();
547 gusLanguageID
= IntGdiGetLanguageID();
549 return STATUS_SUCCESS
;