/*
* ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: dllmain.c,v 1.68 2004/04/09 20:03:18 navaraf Exp $
+/* $Id$
*
* Entry Point for win32k.sys
*/
-#undef WIN32_LEAN_AND_MEAN
-#define WIN32_NO_STATUS
-#include <windows.h>
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-
-#ifdef __USE_W32API
-#include <ddk/ddrawint.h>
-#endif
-#include <ddk/winddi.h>
-
-#include <win32k/win32k.h>
-
-#include <include/winsta.h>
-#include <include/desktop.h>
-#include <include/class.h>
-#include <include/window.h>
-#include <include/menu.h>
-#include <include/object.h>
-#include <include/input.h>
-#include <include/timer.h>
-#include <include/text.h>
-#include <include/caret.h>
-#include <include/hotkey.h>
-#include <include/accelerator.h>
-#include <include/cursoricon.h>
-#include <include/guicheck.h>
-#include <include/hook.h>
+#include <w32k.h>
+#include <win32k/ntddraw.h>
+#include <include/napi.h>
#define NDEBUG
-#include <win32k/debug1.h>
-
-#ifdef __USE_W32API
-typedef NTSTATUS (STDCALL *PW32_PROCESS_CALLBACK)(
- struct _EPROCESS *Process,
- BOOLEAN Create);
-
-typedef NTSTATUS (STDCALL *PW32_THREAD_CALLBACK)(
- struct _ETHREAD *Thread,
- BOOLEAN Create);
-
-VOID STDCALL
-PsEstablishWin32Callouts(
- PW32_PROCESS_CALLBACK W32ProcessCallback,
- PW32_THREAD_CALLBACK W32ThreadCallback,
- PVOID Param3,
- PVOID Param4,
- ULONG W32ThreadSize,
- ULONG W32ProcessSize);
-#endif
-
-extern SSDT Win32kSSDT[];
-extern SSPT Win32kSSPT[];
+#include <debug.h>
+
+BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process);
+
+extern ULONG_PTR Win32kSSDT[];
+extern UCHAR Win32kSSPT[];
extern ULONG Win32kNumberOfSysCalls;
-NTSTATUS STDCALL
-Win32kProcessCallback (struct _EPROCESS *Process,
- BOOLEAN Create)
+PSHARED_SECTION_POOL SessionSharedSectionPool = NULL;
+
+NTSTATUS
+STDCALL
+Win32kProcessCallback(struct _EPROCESS *Process,
+ BOOLEAN Create)
{
- PW32PROCESS Win32Process;
- NTSTATUS Status;
+ PW32PROCESS Win32Process;
+ DECLARE_RETURN(NTSTATUS);
+
+ DPRINT("Enter Win32kProcessCallback\n");
+ UserEnterExclusive();
+
+ /* Get the Win32 Process */
+ Win32Process = PsGetProcessWin32Process(Process);
+
+ /* Allocate one if needed */
+ if (!Win32Process)
+ {
+ /* FIXME - lock the process */
+ Win32Process = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(W32PROCESS),
+ TAG('W', '3', '2', 'p'));
+
+ if (Win32Process == NULL) RETURN( STATUS_NO_MEMORY);
-#if 0
- DbgPrint ("Win32kProcessCallback() called\n");
-#endif
+ RtlZeroMemory(Win32Process, sizeof(W32PROCESS));
+
+ PsSetProcessWin32Process(Process, Win32Process);
+ /* FIXME - unlock the process */
+ }
- Win32Process = Process->Win32Process;
if (Create)
{
-#if 0
- DbgPrint (" Create process\n");
-#endif
+ DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
+
+ InitializeListHead(&Win32Process->ClassList);
- InitializeListHead(&Win32Process->ClassListHead);
- ExInitializeFastMutex(&Win32Process->ClassListLock);
-
InitializeListHead(&Win32Process->MenuListHead);
- ExInitializeFastMutex(&Win32Process->MenuListLock);
InitializeListHead(&Win32Process->PrivateFontListHead);
ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
-
- InitializeListHead(&Win32Process->CursorIconListHead);
- ExInitializeFastMutex(&Win32Process->CursorIconListLock);
+
+ InitializeListHead(&Win32Process->DriverObjListHead);
+ ExInitializeFastMutex(&Win32Process->DriverObjListLock);
Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
- Win32Process->WindowStation = NULL;
- if (Process->Win32WindowStation != NULL)
- {
- Status =
- IntValidateWindowStationHandle(Process->Win32WindowStation,
- UserMode,
- GENERIC_ALL,
- &Win32Process->WindowStation);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Win32K: Failed to reference a window station for "
- "process.\n");
- }
- }
-
- Win32Process->CreatedWindowOrDC = FALSE;
- Win32Process->ManualGuiCheck = FALSE;
+
+ if(Process->Peb != NULL)
+ {
+ /* map the gdi handle table to user land */
+ Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
+ }
+
+ /* setup process flags */
+ Win32Process->Flags = 0;
}
else
{
-#if 0
- DbgPrint (" Destroy process\n");
- DbgPrint (" IRQ level: %lu\n", KeGetCurrentIrql ());
-#endif
- IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId);
+ DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
+ IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId);
IntCleanupMenus(Process, Win32Process);
IntCleanupCurIcons(Process, Win32Process);
+ IntEngCleanupDriverObjs(Process, Win32Process);
+ CleanupMonitorImpl();
+
+ /* no process windows should exist at this point, or the function will assert! */
+ DestroyProcessClasses(Win32Process);
+
+ GDI_CleanupForProcess(Process);
- CleanupForProcess(Process, Process->UniqueProcessId);
+ co_IntGraphicsCheck(FALSE);
- IntGraphicsCheck(FALSE);
+ /*
+ * Deregister logon application automatically
+ */
+ if(LogonProcess == Win32Process)
+ {
+ LogonProcess = NULL;
+ }
}
- return STATUS_SUCCESS;
+ RETURN( STATUS_SUCCESS);
+
+CLEANUP:
+ UserLeave();
+ DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_);
+ END_CLEANUP;
}
-NTSTATUS STDCALL
-Win32kThreadCallback (struct _ETHREAD *Thread,
- BOOLEAN Create)
+NTSTATUS
+STDCALL
+Win32kThreadCallback(struct _ETHREAD *Thread,
+ BOOLEAN Create)
{
- struct _EPROCESS *Process;
- PW32THREAD Win32Thread;
- NTSTATUS Status;
+ struct _EPROCESS *Process;
+ PW32THREAD Win32Thread;
+ DECLARE_RETURN(NTSTATUS);
+
+ DPRINT("Enter Win32kThreadCallback\n");
+ UserEnterExclusive();
+
+ Process = Thread->ThreadsProcess;
+
+ /* Get the Win32 Thread */
+ Win32Thread = PsGetThreadWin32Thread(Thread);
+
+ /* Allocate one if needed */
+ if (!Win32Thread)
+ {
+ /* FIXME - lock the process */
+ Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(W32THREAD),
+ TAG('W', '3', '2', 't'));
-#if 0
- DbgPrint ("Win32kThreadCallback() called\n");
-#endif
+ if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
- Process = Thread->ThreadsProcess;
- Win32Thread = Thread->Win32Thread;
+ RtlZeroMemory(Win32Thread, sizeof(W32THREAD));
+
+ PsSetThreadWin32Thread(Thread, Win32Thread);
+ /* FIXME - unlock the process */
+ }
if (Create)
{
-#if 0
- DbgPrint (" Create thread\n");
-#endif
-
+ HWINSTA hWinSta = NULL;
+ HDESK hDesk = NULL;
+ NTSTATUS Status;
+ PUNICODE_STRING DesktopPath;
+ PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
+
+ DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
+
+ /*
+ * inherit the thread desktop and process window station (if not yet inherited) from the process startup
+ * info structure. See documentation of CreateProcess()
+ */
+ DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
+ Status = IntParseDesktopPath(Process,
+ DesktopPath,
+ &hWinSta,
+ &hDesk);
+ if(NT_SUCCESS(Status))
+ {
+ if(hWinSta != NULL)
+ {
+ if(Process != CsrProcess)
+ {
+ HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
+ if(hProcessWinSta != NULL)
+ {
+ /* our process is already assigned to a different window station, we don't need the handle anymore */
+ NtClose(hWinSta);
+ }
+ }
+ else
+ {
+ NtClose(hWinSta);
+ }
+ }
+
+ if (hDesk != NULL)
+ {
+ Status = ObReferenceObjectByHandle(hDesk,
+ 0,
+ ExDesktopObjectType,
+ KernelMode,
+ (PVOID*)&Win32Thread->Desktop,
+ NULL);
+ NtClose(hDesk);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
+ Win32Thread->Desktop = NULL;
+ }
+ }
+ }
Win32Thread->IsExiting = FALSE;
- IntDestroyCaret(Win32Thread);
+ co_IntDestroyCaret(Win32Thread);
Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
Win32Thread->MessagePumpHookValue = 0;
InitializeListHead(&Win32Thread->WindowListHead);
- ExInitializeFastMutex(&Win32Thread->WindowListLock);
-
- /* By default threads get assigned their process's desktop. */
- Win32Thread->Desktop = NULL;
- if (Process->Win32Desktop != NULL)
- {
- Status = ObReferenceObjectByHandle(Process->Win32Desktop,
- GENERIC_ALL,
- ExDesktopObjectType,
- UserMode,
- (PVOID*)&Win32Thread->Desktop,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Win32K: Failed to reference a desktop for thread.\n");
- }
- }
+ InitializeListHead(&Win32Thread->W32CallbackListHead);
}
else
{
-#if 0
- DbgPrint (" Destroy thread\n");
-#endif
+ PSINGLE_LIST_ENTRY e;
+
+ DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
Win32Thread->IsExiting = TRUE;
HOOK_DestroyThreadHooks(Thread);
- RemoveTimersThread(Thread->Cid.UniqueThread);
UnregisterThreadHotKeys(Thread);
- DestroyThreadWindows(Thread);
+ /* what if this co_ func crash in umode? what will clean us up then? */
+ co_DestroyThreadWindows(Thread);
+ IntBlockInput(Win32Thread, FALSE);
+ MsqDestroyMessageQueue(Win32Thread->MessageQueue);
+ IntCleanupThreadCallbacks(Win32Thread);
+ if(Win32Thread->Desktop != NULL)
+ {
+ ObDereferenceObject(Win32Thread->Desktop);
+ }
+
+ /* cleanup user object references stack */
+ e = PopEntryList(&Win32Thread->ReferencesList);
+ while (e)
+ {
+ PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry);
+ DPRINT1("thread clean: remove reference obj 0x%x\n",ref->obj);
+ ObmDereferenceObject(ref->obj);
+
+ e = PopEntryList(&Win32Thread->ReferencesList);
+ }
+ PsSetThreadWin32Thread(Thread, NULL);
}
- return STATUS_SUCCESS;
+ RETURN( STATUS_SUCCESS);
+
+CLEANUP:
+ UserLeave();
+ DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_);
+ END_CLEANUP;
+}
+
+/* Only used in ntuser/input.c KeyboardThreadMain(). If it's
+ not called there anymore, please delete */
+NTSTATUS
+Win32kInitWin32Thread(PETHREAD Thread)
+{
+ PEPROCESS Process;
+
+ Process = Thread->ThreadsProcess;
+
+ if (Process->Win32Process == NULL)
+ {
+ /* FIXME - lock the process */
+ Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(W32PROCESS));
+
+ if (Process->Win32Process == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(Process->Win32Process, sizeof(W32PROCESS));
+ /* FIXME - unlock the process */
+
+ Win32kProcessCallback(Process, TRUE);
+ }
+
+ if (Thread->Tcb.Win32Thread == NULL)
+ {
+ Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(W32THREAD));
+ if (Thread->Tcb.Win32Thread == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(W32THREAD));
+
+ Win32kThreadCallback(Thread, TRUE);
+ }
+
+ return(STATUS_SUCCESS);
}
/*
* This definition doesn't work
*/
-// BOOL STDCALL DllMain(VOID)
NTSTATUS STDCALL
-DllMain (
+DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS Status;
BOOLEAN Result;
+ W32_CALLOUT_DATA CalloutData;
/*
* Register user mode call interface
1);
if (Result == FALSE)
{
- DbgPrint("Adding system services failed!\n");
+ DPRINT1("Adding system services failed!\n");
return STATUS_UNSUCCESSFUL;
}
- /*
- * Register our per-process and per-thread structures.
- */
- PsEstablishWin32Callouts (Win32kProcessCallback,
- Win32kThreadCallback,
- 0,
- 0,
- sizeof(W32THREAD),
- sizeof(W32PROCESS));
-
+ /*
+ * Register Object Manager Callbacks
+ */
+ CalloutData.WinStaCreate = IntWinStaObjectOpen;
+ CalloutData.WinStaParse = IntWinStaObjectParse;
+ CalloutData.WinStaDelete = IntWinStaObjectDelete;
+ CalloutData.WinStaFind = IntWinStaObjectFind;
+ CalloutData.DesktopCreate = IntDesktopObjectCreate;
+ CalloutData.DesktopDelete = IntDesktopObjectDelete;
+ CalloutData.W32ProcessCallout = Win32kProcessCallback;
+ CalloutData.W32ThreadCallout = Win32kThreadCallback;
+
+ /*
+ * Register our per-process and per-thread structures.
+ */
+ PsEstablishWin32Callouts(&CalloutData);
+
+ Status = IntUserCreateSharedSectionPool(48 * 1024 * 1024, /* 48 MB by default */
+ &SessionSharedSectionPool);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize the shared section pool: Status 0x%x\n", Status);
+ }
+
+ Status = InitUserImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize user implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitHotkeyImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize hotkey implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
Status = InitWindowStationImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize window station implementation!\n");
+ DPRINT1("Failed to initialize window station implementation!\n");
return STATUS_UNSUCCESSFUL;
}
Status = InitClassImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize window class implementation!\n");
+ DPRINT1("Failed to initialize window class implementation!\n");
return STATUS_UNSUCCESSFUL;
}
Status = InitDesktopImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize window station implementation!\n");
+ DPRINT1("Failed to initialize desktop implementation!\n");
return STATUS_UNSUCCESSFUL;
}
Status = InitWindowImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize window implementation!\n");
+ DPRINT1("Failed to initialize window implementation!\n");
return STATUS_UNSUCCESSFUL;
}
Status = InitMenuImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize menu implementation!\n");
+ DPRINT1("Failed to initialize menu implementation!\n");
return STATUS_UNSUCCESSFUL;
}
Status = InitInputImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize input implementation.\n");
+ DPRINT1("Failed to initialize input implementation.\n");
return(Status);
}
Status = InitKeyboardImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize keyboard implementation.\n");
+ DPRINT1("Failed to initialize keyboard implementation.\n");
return(Status);
}
+ Status = InitMonitorImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Failed to initialize monitor implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
Status = MsqInitializeImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize message queue implementation.\n");
+ DPRINT1("Failed to initialize message queue implementation.\n");
return(Status);
}
Status = InitTimerImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize timer implementation.\n");
+ DPRINT1("Failed to initialize timer implementation.\n");
return(Status);
}
Status = InitAcceleratorImpl();
if (!NT_SUCCESS(Status))
{
- DbgPrint("Failed to initialize accelerator implementation.\n");
+ DPRINT1("Failed to initialize accelerator implementation.\n");
+ return(Status);
+ }
+
+ Status = InitGuiCheckImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize GUI check implementation.\n");
return(Status);
}
/* Create stock objects, ie. precreated objects commonly
used by win32 applications */
CreateStockObjects();
+ CreateSysColorObjects();
return STATUS_SUCCESS;
}