Fix the USER32 DLL initialization and cleanup routines to prevent memory/resource...
[reactos.git] / reactos / lib / user32 / misc / dllmain.c
index 7d00df9..a1d8a6f 100644 (file)
-#include <windows.h>
-INT
-STDCALL
-DllMain(
-       PVOID   hinstDll,
-       ULONG   dwReason,
-       PVOID   reserved
-       )
+#include <user32.h>
+#define NDEBUG
+#include <debug.h>
+
+static ULONG User32TlsIndex;
+HINSTANCE User32Instance;
+
+PUSER32_THREAD_DATA
+User32GetThreadData()
+{
+   return ((PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex));
+}
+
+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;
+}
+
+VOID
+CleanupThread(VOID)
 {
-       switch (dwReason)
-       {
-               case DLL_PROCESS_ATTACH:
-                       break;
-               case DLL_THREAD_ATTACH:
-                       break;
-               case DLL_THREAD_DETACH:
-                       break;
-               case DLL_PROCESS_DETACH:
-                       break;
-       }
-       return(1);
+   PUSER32_THREAD_DATA ThreadData;
+
+   ThreadData = (PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex);
+   HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, ThreadData);
+   TlsSetValue(User32TlsIndex, 0);
 }
 
+BOOL
+Init(VOID)
+{
+   /* 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;
+}
+
+VOID
+Cleanup(VOID)
+{
+   DeleteCriticalSection(&U32AccelCacheLock);
+   MenuCleanup();
+   MessageCleanup();
+   DeleteFrameBrushes();
+   GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
+   TlsFree(User32TlsIndex);
+}
+
+INT STDCALL
+DllMain(
+   IN PVOID hInstanceDll,
+   IN ULONG dwReason,
+   IN PVOID reserved)
+{
+   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;
+}