Fixed sequence of DLL_PROCESS_DETACH notification calls.
Moved PE_MODREF flags to WINE_MODREF level.
Better handling of LoadLibraryEx flags.
PE_InitTls() changed to work only on the current thread.

diff --git a/loader/module.c b/loader/module.c
index 86cc727..9d1008e 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -73,37 +73,84 @@
 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
                                      DWORD type, LPVOID lpReserved )
 {
-    int i;
+    WINE_MODREF *xwm;
+    int i, skip = FALSE;
 
-    assert( wm && !wm->initDone );
-    TRACE( module, "(%08x,%ld,%p) - START\n", 
-           wm->module, type, lpReserved );
+    assert( wm && !(wm->flags & WINE_MODREF_MARKER) );
+    TRACE( module, "(%s,%08x,%ld,%p) - START\n", 
+           wm->modname, wm->module, type, lpReserved );
 
     /* Tag current MODREF to prevent recursive loop */
-    wm->initDone = TRUE;
+    wm->flags |= WINE_MODREF_MARKER;
 
-    /* Recursively initialize all child DLLs */
-    for ( i = 0; i < wm->nDeps; i++ )
-        if ( wm->deps[i] && !wm->deps[i]->initDone )
-            MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
-
-    /* Now we can call the initialization routine */
-    switch ( wm->type )
+    switch ( type )
     {
-    case MODULE32_PE:
-        PE_InitDLL( wm, type, lpReserved );
+    default:
+    case DLL_PROCESS_ATTACH:
+    case DLL_THREAD_ATTACH:
+        /* Recursively attach all DLLs this one depends on */
+        for ( i = 0; i < wm->nDeps; i++ )
+            if ( wm->deps[i] && !(wm->deps[i]->flags & WINE_MODREF_MARKER) )
+                MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
         break;
 
-    case MODULE32_ELF:
-    	/* no need to do that, dlopen() already does */
-    	break;
-    default:
-    	ERR(module, "wine_modref type %d not handled.\n", wm->type);
+    case DLL_PROCESS_DETACH:
+    case DLL_THREAD_DETACH:
+        /* Recursively detach all DLLs that depend on this one */
+        for ( xwm = PROCESS_Current()->modref_list; xwm; xwm = xwm->next )
+            if ( !(xwm->flags & WINE_MODREF_MARKER) )
+                for ( i = 0; i < xwm->nDeps; i++ )
+                    if ( xwm->deps[i] == wm )
+                    {
+                        MODULE_DoInitializeDLLs( xwm, type, lpReserved );
+                        break;
+                    }
         break;
     }
 
-    TRACE( module, "(%08x,%ld,%p) - END\n", 
-           wm->module, type, lpReserved );
+    /* Evaluate module flags */
+
+    if (    ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
+         || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
+         || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
+        skip = TRUE;
+
+    if ( type == DLL_PROCESS_ATTACH )
+        if ( wm->flags & WINE_MODREF_PROCESS_ATTACHED )
+            skip = TRUE;
+        else
+            wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
+
+    if ( type == DLL_PROCESS_DETACH )
+        if ( wm->flags & WINE_MODREF_PROCESS_DETACHED )
+            skip = TRUE;
+        else
+            wm->flags |= WINE_MODREF_PROCESS_DETACHED;
+
+    if ( !skip )
+    {
+        /* Now we can call the initialization routine */
+        TRACE( module, "(%s,%08x,%ld,%p) - CALL\n", 
+               wm->modname, wm->module, type, lpReserved );
+
+        switch ( wm->type )
+        {
+        case MODULE32_PE:
+            PE_InitDLL( wm, type, lpReserved );
+            break;
+
+        case MODULE32_ELF:
+            /* no need to do that, dlopen() already does */
+            break;
+
+        default:
+           ERR(module, "wine_modref type %d not handled.\n", wm->type);
+           break;
+        }
+    }
+
+    TRACE( module, "(%s,%08x,%ld,%p) - END\n", 
+           wm->modname, wm->module, type, lpReserved );
 }
 
 void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
@@ -119,7 +166,7 @@
 
     /* First, check whether initialization is currently in progress */
     for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
-        if ( wm->initDone )
+        if ( wm->flags & WINE_MODREF_MARKER )
         {
             inProgress = TRUE;
             break;
@@ -135,7 +182,7 @@
         if ( root )
         {
             wm = MODULE32_LookupHMODULE( root );
-            if ( wm && !wm->initDone )
+            if ( wm && !(wm->flags & WINE_MODREF_MARKER) )
                 MODULE_DoInitializeDLLs( wm, type, lpReserved );
         }
         else
@@ -147,9 +194,26 @@
         if ( !root )
         {
             /* If called for main EXE, initialize all DLLs */
-            for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
-                if ( !wm->initDone )
-                    MODULE_DoInitializeDLLs( wm, type, lpReserved );
+            switch ( type )
+            {
+            default:  /* Hmmm. */
+            case DLL_PROCESS_ATTACH:
+            case DLL_THREAD_ATTACH:
+                for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
+                    if ( !wm->next )
+                        break;
+                for ( ; wm; wm = wm->prev )
+                    if ( !(wm->flags & WINE_MODREF_MARKER) )
+                        MODULE_DoInitializeDLLs( wm, type, lpReserved );
+                break;
+
+            case DLL_PROCESS_DETACH:
+            case DLL_THREAD_DETACH:
+                for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
+                    if ( !(wm->flags & WINE_MODREF_MARKER) )
+                        MODULE_DoInitializeDLLs( wm, type, lpReserved );
+                break;
+            }
         }
         else
         {
@@ -160,7 +224,7 @@
 
         /* We're finished, so we reset all recursion flags */
         for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
-            wm->initDone = FALSE;
+            wm->flags &= ~WINE_MODREF_MARKER;
     }
 
     TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
@@ -169,6 +233,49 @@
     LeaveCriticalSection( &PROCESS_Current()->crit_section );
 }
 
+/****************************************************************************
+ *              DisableThreadLibraryCalls (KERNEL32.74)
+ *
+ * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
+ */
+BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
+{
+    WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+    if ( !wm ) return FALSE;
+
+    wm->flags |= WINE_MODREF_NO_DLL_CALLS;
+    return TRUE;
+}
+
+/****************************************************************************
+ *              MODULE_IncRefCount
+ */
+static void MODULE_IncRefCount( HMODULE hModule )
+{
+    WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+    if ( !wm ) return;
+
+    EnterCriticalSection( &PROCESS_Current()->crit_section );
+    wm->refCount++;
+    LeaveCriticalSection( &PROCESS_Current()->crit_section );
+}
+
+/****************************************************************************
+ *              MODULE_DecRefCount
+ */
+static int MODULE_DecRefCount( HMODULE hModule )
+{
+    int retv;
+    WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+    if ( !wm ) return 0;
+
+    EnterCriticalSection( &PROCESS_Current()->crit_section );
+    if ( ( retv = wm->refCount ) > 0 ) wm->refCount--;
+    LeaveCriticalSection( &PROCESS_Current()->crit_section );
+
+    return retv;
+}
+
 
 /***********************************************************************
  *           MODULE_CreateDummyModule
@@ -1103,15 +1210,14 @@
     HMODULE hmod;
     hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
 
-    /* at least call not the dllmain...*/
-    if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
-    { FIXME(module,"flag not properly supported %lx\n", flags);
-      return hmod;
-    }
+    if ( hmod >= 32 )
+    {
+        /* Increment RefCount */
+        MODULE_IncRefCount( hmod );
 
-    /* initialize DLL just loaded */
-    if ( hmod >= 32 )       
-        MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
+        /* Initialize DLL just loaded */
+        MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
+    }
 
     return hmod;
 }
@@ -1159,8 +1265,10 @@
  */
 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
 {
-    FIXME(module,"(0x%08x): stub\n", hLibModule);
-    return TRUE;  /* FIXME */
+    if ( MODULE_DecRefCount( hLibModule ) != 1 ) return TRUE;
+
+    FIXME(module,"(0x%08x): should unload now\n", hLibModule);
+    return TRUE; /* FIXME */
 }
 
 /***********************************************************************