diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 668744c1ecb1937610856327c21608f968fe1eb8..a89306cd502165f1f54af5a55e0894d935557180 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -55,6 +55,14 @@ static WINE_EXCEPTION_FILTER(page_fault)
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
+static const char * const reason_names[] =
+{
+    "PROCESS_DETACH",
+    "PROCESS_ATTACH",
+    "THREAD_ATTACH",
+    "THREAD_DETACH"
+};
+
 static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
 static WINE_MODREF *cached_modref;
 static WINE_MODREF *current_modref;
@@ -388,13 +396,37 @@ WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
     return wm;
 }
 
+
+/*************************************************************************
+ *              call_tls_callbacks
+ */
+static void call_tls_callbacks( HMODULE module, UINT reason )
+{
+    const IMAGE_TLS_DIRECTORY *dir;
+    const PIMAGE_TLS_CALLBACK *callback;
+    ULONG dirsize;
+
+    dir = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
+    if (!dir || !dir->AddressOfCallBacks) return;
+
+    for (callback = dir->AddressOfCallBacks; *callback; callback++)
+    {
+        if (TRACE_ON(relay))
+            DPRINTF("%04lx:Call TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
+                    GetCurrentThreadId(), *callback, module, reason_names[reason] );
+        (*callback)( module, reason, NULL );
+        if (TRACE_ON(relay))
+            DPRINTF("%04lx:Ret  TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
+                    GetCurrentThreadId(), *callback, module, reason_names[reason] );
+    }
+}
+
+
 /*************************************************************************
  *              MODULE_InitDLL
  */
-static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
+static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
 {
-    static const char * const typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH",
-                                             "THREAD_ATTACH", "THREAD_DETACH" };
     char mod_name[32];
     BOOL retv = TRUE;
     DLLENTRYPROC entry = wm->ldr.EntryPoint;
@@ -403,6 +435,7 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
     /* Skip calls for modules loaded with special load flags */
 
     if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return TRUE;
+    if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
     if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return TRUE;
 
     if (TRACE_ON(relay))
@@ -410,20 +443,20 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
         size_t len = max( strlen(wm->modname), sizeof(mod_name)-1 );
         memcpy( mod_name, wm->modname, len );
         mod_name[len] = 0;
-        DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p)\n",
-                GetCurrentThreadId(), entry, module, mod_name, type, lpReserved );
+        DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p (%s),reason=%s,res=%p)\n",
+                GetCurrentThreadId(), entry, module, mod_name, reason_names[reason], lpReserved );
     }
-    else TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, typeName[type], lpReserved );
+    else TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, reason_names[reason], lpReserved );
 
-    retv = entry( module, type, lpReserved );
+    retv = entry( module, reason, lpReserved );
 
     /* The state of the module list may have changed due to the call
        to the dll. We cannot assume that this module has not been
        deleted.  */
     if (TRACE_ON(relay))
-        DPRINTF("%04lx:Ret  PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p) retval=%x\n",
-                GetCurrentThreadId(), entry, module, mod_name, type, lpReserved, retv );
-    else TRACE("(%p,%s,%p) - RETURN %d\n", module, typeName[type], lpReserved, retv );
+        DPRINTF("%04lx:Ret  PE DLL (proc=%p,module=%p (%s),reason=%s,res=%p) retval=%x\n",
+                GetCurrentThreadId(), entry, module, mod_name, reason_names[reason], lpReserved, retv );
+    else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
 
     return retv;
 }
@@ -526,7 +559,7 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
  * sequence at MODULE_DllProcessAttach.  Unless the bForceDetach flag
  * is set, only DLLs with zero refcount are notified.
  */
-void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
+static void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
 {
     WINE_MODREF *wm;
 
@@ -603,7 +636,7 @@ NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
     RtlEnterCriticalSection( &loader_section );
 
     wm = get_modref( hModule );
-    if ( !wm )
+    if (!wm || wm->ldr.TlsIndex != -1)
         ret = STATUS_DLL_NOT_FOUND;
     else
         wm->ldr.Flags |= LDR_NO_DLL_CALLS;
@@ -1065,24 +1098,23 @@ NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi,
  *		LdrShutdownProcess (NTDLL.@)
  *
  */
-NTSTATUS    WINAPI  LdrShutdownProcess(void)
+void WINAPI LdrShutdownProcess(void)
 {
     TRACE("()\n");
     MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
-    return STATUS_SUCCESS; /* FIXME */
 }
 
 /******************************************************************
  *		LdrShutdownThread (NTDLL.@)
  *
  */
-NTSTATUS WINAPI LdrShutdownThread(void)
+void WINAPI LdrShutdownThread(void)
 {
     WINE_MODREF *wm;
     TRACE("()\n");
 
     /* don't do any detach calls if process is exiting */
-    if (process_detaching) return STATUS_SUCCESS;
+    if (process_detaching) return;
     /* FIXME: there is still a race here */
 
     RtlEnterCriticalSection( &loader_section );
@@ -1098,7 +1130,6 @@ NTSTATUS WINAPI LdrShutdownThread(void)
     }
 
     RtlLeaveCriticalSection( &loader_section );
-    return STATUS_SUCCESS; /* FIXME */
 }
 
 /***********************************************************************
diff --git a/include/module.h b/include/module.h
index 86438fc20ca92f79909c4f69e23f09f85dd3606a..96837185fe697770509470a8146332fefad6499a 100644
--- a/include/module.h
+++ b/include/module.h
@@ -182,7 +182,6 @@ enum binary_type
 
 /* module.c */
 extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
-extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
 extern void MODULE_DllThreadAttach( LPVOID lpReserved );
 extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
 extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
diff --git a/include/winternl.h b/include/winternl.h
index 77f92fb908d4286a24cf191a6e51a7c86b321c49..0cfac3844ef4ea6295cca5fba3d403818b1ea19b 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -844,6 +844,8 @@ void WINAPIV DbgPrint(LPCSTR fmt, ...);
 NTSTATUS  WINAPI LdrAccessResource(HMODULE,const IMAGE_RESOURCE_DATA_ENTRY*,void**,PULONG);
 NTSTATUS  WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DIRECTORY**);
 NTSTATUS  WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**);
+void      WINAPI LdrShutdownProcess(void);
+void      WINAPI LdrShutdownThread(void);
 NTSTATUS  WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
 NTSTATUS  WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
 NTSTATUS  WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,PVOID,ULONG*,ULONG,ULONG);
@@ -1277,8 +1279,6 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**);
 NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*);
 NTSTATUS WINAPI LdrLockLoaderLock(ULONG,ULONG*,ULONG*);
 NTSTATUS WINAPI LdrQueryProcessModuleInformation(SYSTEM_MODULE_INFORMATION*, ULONG, ULONG*);
-NTSTATUS WINAPI LdrShutdownProcess(void);
-NTSTATUS WINAPI LdrShutdownThread(void);
 NTSTATUS WINAPI LdrUnloadDll(HMODULE);
 NTSTATUS WINAPI LdrUnlockLoaderLock(ULONG,ULONG);
 
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 7508342d5cad1bad7112539e1b194074995754ad..deffca76253463622d0051af93244a45ab9867d2 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -421,14 +421,6 @@ void PE_InitTls( void )
                 NtAllocateVirtualMemory( GetCurrentProcess(), &mem, NULL, &size,
                                          MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
 		memcpy(mem,_fixup_address(&(peh->OptionalHeader),delta,(LPVOID)pdir->StartAddressOfRawData),datasize);
-		if (pdir->AddressOfCallBacks) {
-		     PIMAGE_TLS_CALLBACK *cbs;
-
-		     cbs = _fixup_address(&(peh->OptionalHeader),delta,pdir->AddressOfCallBacks);
-		     if (*cbs)
-		       FIXME("TLS Callbacks aren't going to be called\n");
-		}
-
 		TlsSetValue( wm->ldr.TlsIndex, mem );
 	}
 }