Fix the USER32 DLL initialization and cleanup routines to prevent memory/resource...
[reactos.git] / reactos / lib / user32 / misc / dllmain.c
index 8e72095..a1d8a6f 100644 (file)
-#include <windows.h>
+#include <user32.h>
+#define NDEBUG
 #include <debug.h>
-#include <user32/callback.h>
 
-#ifdef DBG
+static ULONG User32TlsIndex;
+HINSTANCE User32Instance;
 
-/* See debug.h for debug/trace constants */
-DWORD DebugTraceLevel = MIN_TRACE;
+PUSER32_THREAD_DATA
+User32GetThreadData()
+{
+   return ((PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex));
+}
 
-#endif /* DBG */
+BOOL
+InitThread(VOID)
+{
+   PUSER32_THREAD_DATA ThreadData;
+
+   ThreadData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                          sizeof(USER32_THREAD_DATA));
+   if (ThreadData == NULL)
+      return FALSE;
+   if (!TlsSetValue(User32TlsIndex, ThreadData))
+      return FALSE;
+   return TRUE;
+}
 
-/* To make the linker happy */
-VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
+VOID
+CleanupThread(VOID)
+{
+   PUSER32_THREAD_DATA ThreadData;
 
-HANDLE ProcessHeap;
-HWINSTA ProcessWindowStation;
+   ThreadData = (PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex);
+   HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, ThreadData);
+   TlsSetValue(User32TlsIndex, 0);
+}
 
-DWORD
+BOOL
 Init(VOID)
 {
-  DWORD Status;
-
-  ProcessHeap = RtlGetProcessHeap();
-
-  /* Set up the kernel callbacks. */
-  NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] =
-    (PVOID)User32CallWindowProcFromKernel;
-
-  //ProcessWindowStation = CreateWindowStationW(L"WinStaName",0,GENERIC_ALL,NULL);
-  //Desktop = CreateDesktopA(NULL,NULL,NULL,0,0,NULL);
-
-  //GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
-
-  return Status;
+   /* Set up the kernel callbacks. */
+   NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] =
+      (PVOID)User32CallWindowProcFromKernel;
+   NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] =
+      (PVOID)User32CallSendAsyncProcForKernel;
+   NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] =
+      (PVOID)User32LoadSysMenuTemplateForKernel;
+   NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] =
+      (PVOID)User32SetupDefaultCursors;
+   NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] =
+      (PVOID)User32CallHookProcFromKernel;
+
+   /* Allocate an index for user32 thread local data. */
+   User32TlsIndex = TlsAlloc();
+   if (User32TlsIndex != TLS_OUT_OF_INDEXES)
+   {
+      if (MessageInit())
+      {
+         if (MenuInit())
+         {
+            InitializeCriticalSection(&U32AccelCacheLock);
+            GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
+            InitStockObjects();
+
+            return TRUE;
+         }
+         MessageCleanup();
+      }
+      TlsFree(User32TlsIndex);
+   }
+
+   return FALSE;
 }
 
-DWORD
+VOID
 Cleanup(VOID)
 {
-  DWORD Status;
-
-  //CloseWindowStation(ProcessWindowStation);
-
-  //GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
-
-  return Status;
+   DeleteCriticalSection(&U32AccelCacheLock);
+   MenuCleanup();
+   MessageCleanup();
+   DeleteFrameBrushes();
+   GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
+   TlsFree(User32TlsIndex);
 }
 
 INT STDCALL
-DllMain(PVOID  hinstDll,
-       ULONG   dwReason,
-       PVOID   reserved)
+DllMain(
+   IN PVOID hInstanceDll,
+   IN ULONG dwReason,
+   IN PVOID reserved)
 {
-  D(MAX_TRACE, ("hinstDll (0x%X)  dwReason (0x%X)\n", hinstDll, dwReason));
-
-  switch (dwReason)
-    {
-    case DLL_PROCESS_ATTACH:
-      Init();
-      break;
-    case DLL_THREAD_ATTACH:
-      break;
-    case DLL_THREAD_DETACH:
-      break;
-    case DLL_PROCESS_DETACH:
-      Cleanup();
-      break;
-    }
-  return(1);
+   switch (dwReason)
+   {
+      case DLL_PROCESS_ATTACH:
+         User32Instance = hInstanceDll;
+         hProcessHeap = RtlGetProcessHeap();
+         if (!Init())
+            return FALSE;
+         if (!InitThread())
+         {
+            Cleanup();
+            return FALSE;
+         }
+         break;
+
+      case DLL_THREAD_ATTACH:
+         if (!InitThread())
+            return FALSE;
+         break;
+
+      case DLL_THREAD_DETACH:
+         CleanupThread();
+         break;
+
+      case DLL_PROCESS_DETACH:
+         CleanupThread();
+         Cleanup();
+         break;
+   }
+
+   return TRUE;
 }
-