- Add flags for NtCreateProcessEx for upcoming patch.
[reactos.git] / reactos / subsys / win32k / main / dllmain.c
index 3742656..94eb7a8 100644 (file)
  *
  *  Entry Point for win32k.sys
  */
+
 #include <w32k.h>
+#include <win32k/ntddraw.h>
+#include <include/napi.h>
 
 #define NDEBUG
-#include <win32k/debug1.h>
 #include <debug.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
-
 BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process);
 
-extern SSDT Win32kSSDT[];
-extern SSPT Win32kSSPT[];
+extern ULONG_PTR Win32kSSDT[];
+extern UCHAR Win32kSSPT[];
 extern ULONG Win32kNumberOfSysCalls;
 
 PSHARED_SECTION_POOL SessionSharedSectionPool = NULL;
 
-NTSTATUS STDCALL
-Win32kProcessCallback (struct _EPROCESS *Process,
-                    BOOLEAN Create)
+NTSTATUS 
+STDCALL
+Win32kProcessCallback(struct _EPROCESS *Process,
+                      BOOLEAN Create)
 {
-  PW32PROCESS Win32Process;
-  
-  Win32Process = Process->Win32Process;
+    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);
+
+        RtlZeroMemory(Win32Process, sizeof(W32PROCESS));
+        
+        PsSetProcessWin32Process(Process, Win32Process);
+        /* FIXME - unlock the process */
+    }
+
   if (Create)
     {
       DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
 
-      InitializeListHead(&Win32Process->ClassListHead);
-      ExInitializeFastMutex(&Win32Process->ClassListLock);
-      
+      InitializeListHead(&Win32Process->ClassList);
+
       InitializeListHead(&Win32Process->MenuListHead);
-      ExInitializeFastMutex(&Win32Process->MenuListLock);      
 
       InitializeListHead(&Win32Process->PrivateFontListHead);
       ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
-      
+
       InitializeListHead(&Win32Process->DriverObjListHead);
       ExInitializeFastMutex(&Win32Process->DriverObjListLock);
 
       Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
-      
+
       if(Process->Peb != NULL)
       {
         /* map the gdi handle table to user land */
         Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
       }
-      
+
       /* setup process flags */
       Win32Process->Flags = 0;
     }
@@ -95,12 +99,14 @@ Win32kProcessCallback (struct _EPROCESS *Process,
       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);
 
-      IntGraphicsCheck(FALSE);
-      
+      co_IntGraphicsCheck(FALSE);
+
       /*
        * Deregister logon application automatically
        */
@@ -110,19 +116,47 @@ Win32kProcessCallback (struct _EPROCESS *Process,
       }
     }
 
-  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;
+    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'));
 
-  Process = Thread->ThreadsProcess;
-  Win32Thread = Thread->Tcb.Win32Thread;
+        if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
+
+        RtlZeroMemory(Win32Thread, sizeof(W32THREAD));
+        
+        PsSetThreadWin32Thread(Thread, Win32Thread);
+        /* FIXME - unlock the process */
+    }
   if (Create)
     {
       HWINSTA hWinSta = NULL;
@@ -132,7 +166,7 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
       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()
@@ -161,40 +195,41 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
           }
         }
 
-        Win32Thread->hDesktop = hDesk;
-
-        Status = ObReferenceObjectByHandle(hDesk,
-                 0,
-                 ExDesktopObjectType,
-                 KernelMode,
-                 (PVOID*)&Win32Thread->Desktop,
-                 NULL);
-
-        if(!NT_SUCCESS(Status))
+        if (hDesk != NULL)
         {
-          DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
-          Win32Thread->Desktop = 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);
       InitializeListHead(&Win32Thread->W32CallbackListHead);
     }
   else
     {
+      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);
       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);
@@ -202,12 +237,69 @@ Win32kThreadCallback (struct _ETHREAD *Thread,
       {
         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
+ */
 NTSTATUS STDCALL
 DriverEntry (
   IN   PDRIVER_OBJECT  DriverObject,
@@ -215,6 +307,7 @@ DriverEntry (
 {
   NTSTATUS Status;
   BOOLEAN Result;
+  W32_CALLOUT_DATA CalloutData;
 
   /*
    * Register user mode call interface
@@ -231,23 +324,44 @@ DriverEntry (
       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))
   {
@@ -345,7 +459,7 @@ DriverEntry (
      used by win32 applications */
   CreateStockObjects();
   CreateSysColorObjects();
-  
+
   return STATUS_SUCCESS;
 }