Index: src/core/dll_helper.d
===================================================================
--- src/core/dll_helper.d	(revision 0)
+++ src/core/dll_helper.d	(revision 0)
@@ -0,0 +1,290 @@
+/**
+ * This module provides OS specific helper function for DLL support
+ */
+
+module core.dll_helper;
+
+version( Windows )
+{
+    import std.c.windows.windows;
+    import core.stdc.string;
+
+    public import core.thread_helper;
+
+    ///////////////////////////////////////////////////////////////////
+    // support fixing implicite TLS for dynamically loaded DLLs on Windows XP
+
+    extern (C)
+    {
+	extern __gshared void* _tlsstart;
+	extern __gshared void* _tlsend;
+	extern __gshared int   _tls_index;
+	extern __gshared void* _tls_callbacks_a;
+    }
+
+private:
+    struct LdrpTlsListEntry
+    {
+	LdrpTlsListEntry* next;
+	LdrpTlsListEntry* prev;
+	void* tlsstart;
+	void* tlsend;
+	void* ptr_tlsindex;
+	void* callbacks;
+	void* zerofill;
+	int   tlsindex;
+    }
+
+    alias extern(Windows)
+    void* fnRtlAllocateHeap(void* HeapHandle, uint Flags, uint Size);
+
+// LdrInitializeThunk
+// -> _LdrpInitialize@12
+// -> _LdrpInitializeThread@4
+// -> _LdrpAllocateTls@0
+// -> je chunk
+//     _LdrpNumberOfTlsEntries
+//     _NtdllBaseTag
+//     _LdrpTlsList_first
+
+    void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative )
+    {
+	if( !adr )
+	    return null;
+
+	ubyte* code = cast(ubyte*) adr;
+	for( int p = 0; p < len; p++ )
+	{
+	    if( code[ p .. p + pattern.length ] == pattern[ 0 .. $ ] )
+	    {
+		ubyte* padr = code + p + pattern.length;
+		if( relative )
+		    return padr + 4 + *cast(int*) padr;
+		return *cast(void**) padr;
+	    }
+	}
+	return null;
+    }
+
+    __gshared int* pNtdllBaseTag;
+
+    __gshared ubyte[] jmp_LdrpInitialize = [ 0x33, 0xED, 0xE9 ]; // xor ebp,ebp; jmp _LdrpInitialize
+    __gshared ubyte[] jmp__LdrpInitialize = [ 0x5D, 0xE9 ]; // pop ebp; jmp __LdrpInitialize
+    __gshared ubyte[] call_LdrpInitializeThread = [ 0xFF, 0x75, 0x08, 0xE8 ]; // push [ebp+8]; call _LdrpInitializeThread
+    __gshared ubyte[] call_LdrpAllocateTls = [ 0x00, 0x00, 0xE8 ]; // jne 0xc3; call _LdrpAllocateTls
+    __gshared ubyte[] jne_LdrpAllocateTls = [ 0x0f, 0x85 ]; // jne body_LdrpAllocateTls
+    __gshared ubyte[] mov_LdrpNumberOfTlsEntries = [ 0x8B, 0x0D ]; // mov ecx, _LdrpNumberOfTlsEntries
+    __gshared ubyte[] mov_NtdllBaseTag = [ 0x51, 0x8B, 0x0D ]; // push ecx; mov ecx, _NtdllBaseTag
+    __gshared ubyte[] mov_LdrpTlsListEntry = [ 0x8B, 0x3D ]; // mov edi, _LdrpTlsListEntry
+
+    LdrpTlsListEntry* addTlsListEntry( void** peb, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+    {
+	HANDLE hnd = GetModuleHandleA( "NTDLL" );
+	assert( hnd, "cannot get module handle for ntdll" );
+	ubyte* fn = cast(ubyte*) GetProcAddress( hnd, "LdrInitializeThunk" );
+	assert( fn, "cannot find LdrInitializeThunk in ntdll" );
+
+	try
+	{
+	    void* pLdrpInitialize = findCodeReference( fn, 20, jmp_LdrpInitialize, true );
+
+	    void* p_LdrpInitialize = findCodeReference( pLdrpInitialize, 40, jmp__LdrpInitialize, true );
+
+	    void* pLdrpInitializeThread = findCodeReference( p_LdrpInitialize, 200, call_LdrpInitializeThread, true );
+
+	    void* pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 40, call_LdrpAllocateTls, true );
+
+	    void* pBodyAllocateTls = findCodeReference( pLdrpAllocateTls, 40, jne_LdrpAllocateTls, true );
+
+	    int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 20, mov_LdrpNumberOfTlsEntries, false );
+	    
+	    pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag, false );
+
+	    LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 60, mov_LdrpTlsListEntry, false );
+
+	    if( !pLdrpNumberOfTlsEntries || !pNtdllBaseTag || !pLdrpTlsList )
+		return null;
+
+	    fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
+	    if( !fnAlloc )
+		return null;
+	
+	    void* heap = peb[6];
+	    LdrpTlsListEntry* entry = cast(LdrpTlsListEntry*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, LdrpTlsListEntry.sizeof );
+	    if( !entry )
+		return null;
+
+	    entry.tlsstart = tlsstart;
+	    entry.tlsend = tlsend;
+	    entry.ptr_tlsindex = tlsindex;
+	    entry.callbacks = tls_callbacks_a;
+	    entry.zerofill = null;
+	    entry.tlsindex = *pLdrpNumberOfTlsEntries;
+
+	    *tlsindex = *pLdrpNumberOfTlsEntries;
+	    entry.next = pLdrpTlsList;
+	    entry.prev = pLdrpTlsList.prev;
+	    pLdrpTlsList.prev.next = entry;
+	    pLdrpTlsList.prev = entry;
+	    (*pLdrpNumberOfTlsEntries)++;
+
+	    return entry;
+	}
+	catch( Exception e )
+	{
+	    // assert( false, e.msg );
+	    return null;
+	}
+    }
+	
+    bool addTlsData( void** teb, void* tlsstart, void* tlsend, int tlsindex )
+    {
+	try
+	{
+	    HANDLE hnd = GetModuleHandleA( "NTDLL" );
+	    assert( hnd, "cannot get module handle for ntdll" );
+
+	    fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
+	    if( !fnAlloc )
+		return false;
+	
+	    void** peb = cast(void**) teb[12];
+	    void* heap = peb[6];
+
+	    int sz = tlsend - tlsstart;
+	    void* tlsdata = cast(void*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, sz );
+	    if( !tlsdata )
+		return false;
+
+	    core.stdc.string.memcpy( tlsdata, tlsstart, sz ); // no relocations!
+    	
+	    void** array = cast(void**) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, (tlsindex + 1) * (void*).sizeof );
+	    if( !array )
+		return false;
+
+	    if( tlsindex > 0 && teb[11] )
+		core.stdc.string.memcpy( array, teb[11], tlsindex * (void*).sizeof); // copy tls-pointers
+	    array[tlsindex] = tlsdata;
+	    teb[11] = cast(void*) array;
+	}
+	catch( Exception e )
+	{
+	    // assert( false, e.msg );
+	    return false;
+	}
+	return true;
+    }
+
+    alias bool BOOLEAN;
+
+    struct UNICODE_STRING
+    {
+	short Length;
+	short MaximumLength;
+	// CAUTION: May not be null-terminated.
+	wchar* Buffer;
+    }
+
+    struct LIST_ENTRY
+    {
+	LIST_ENTRY* next;
+	LIST_ENTRY* prev;
+    }
+
+    struct LDR_MODULE 
+    {
+	LIST_ENTRY      InLoadOrderModuleList;
+	LIST_ENTRY      InMemoryOrderModuleList;
+	LIST_ENTRY      InInitializationOrderModuleList;
+	PVOID           BaseAddress;
+	PVOID           EntryPoint;
+	ULONG           SizeOfImage;
+	UNICODE_STRING  FullDllName;
+	UNICODE_STRING  BaseDllName;
+	ULONG           Flags; // 0x80000,0x40000,4: no thread-init, 
+	SHORT           LoadCount;
+	SHORT           TlsIndex;
+	LIST_ENTRY      HashTableEntry;
+	ULONG           TimeDateStamp;
+    }
+
+    struct PEB_LDR_DATA 
+    {
+	ULONG           Length;
+	BOOLEAN         Initialized;
+	PVOID           SsHandle;
+	LIST_ENTRY      InLoadOrderModuleList;
+	LIST_ENTRY      InMemoryOrderModuleList;
+	LIST_ENTRY      InInitializationOrderModuleList;
+    }
+
+    bool setDllTlsUsage( HINSTANCE hInstance, void** peb )
+    {
+	try
+	{
+	    PEB_LDR_DATA* ldrData = cast(PEB_LDR_DATA*) peb[3];
+
+	    LDR_MODULE *thisMod;
+	    LIST_ENTRY* root = &ldrData.InLoadOrderModuleList;
+	    for(LIST_ENTRY* entry = root.next; entry != root; entry = entry.next)
+	    {
+		    LDR_MODULE *ldrMod = cast(LDR_MODULE*) entry;
+		    if(ldrMod.BaseAddress == hInstance)
+			    thisMod = ldrMod;
+	    }
+
+	    if( !thisMod )
+		return false;
+
+	    thisMod.TlsIndex = -1;  // uses TLS (not the index itself)
+	    thisMod.LoadCount = -1; // never unload
+	    return true;
+	}
+	catch( Exception e )
+	{
+	    // assert( false, e.msg );
+	    return false;
+	}
+    }
+
+    public bool dll_fixTLS( HINSTANCE hInstance, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+    {
+	if( _tls_index != 0 )
+	    return true;
+
+	void** teb;
+	void** peb;
+	void** tlsarray;
+	asm 
+	{
+	    mov EAX,FS:[0x18]; // linear address of TEB
+	    mov teb,EAX;
+	    mov EAX,FS:[0x2c]; 
+	    mov tlsarray, EAX; 
+	    mov EAX,FS:[0x30]; 
+	    mov peb, EAX; 
+	}
+	if( tlsarray && tlsarray[0] == tlsstart )
+	    return true;
+
+	LdrpTlsListEntry* entry = addTlsListEntry( peb, tlsstart, tlsend, tls_callbacks_a, tlsindex );
+	if( !entry )
+	    return false;
+
+	if( !enumProcessThreads( 
+	    function (uint id, void* context) {
+		LdrpTlsListEntry* entry = cast(LdrpTlsListEntry*) context;
+		return addTlsData( getTEB( id ), entry.tlsstart, entry.tlsend, entry.tlsindex ); 
+	    }, entry ) )
+	    return false;
+
+	if( !setDllTlsUsage( hInstance, peb ) )
+	    return false;
+
+//	char* tstart = cast(char*) findSectionInMem (hInstance, ".tls");
+//	_tls_index = 1;
+//	p[_tls_index] = cast(int)tstart;
+
+	return true;
+    }
+}
Index: src/core/thread.d
===================================================================
--- src/core/thread.d	(revision 255)
+++ src/core/thread.d	(working copy)
@@ -98,6 +98,7 @@
     {
         import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
         import core.sys.windows.windows;
+        import core.thread_helper;
 
         const DWORD TLS_OUT_OF_INDEXES  = 0xFFFFFFFF;
 
@@ -192,7 +193,6 @@
             return 0;
         }
 
-
         //
         // Copy of the same-named function in phobos.std.thread--it uses the
         // Windows naming convention to be consistent with GetCurrentThreadId
@@ -1092,7 +1092,11 @@
         //       on why this might occur.
         version( Windows )
         {
-            return cast(Thread) TlsGetValue( sm_this );
+            Thread t = cast(Thread) TlsGetValue( sm_this );
+	    if( t is null )
+		// if the thread has been attached from another thread, the tls value was not set
+		setThis( t = findThread( GetCurrentThreadId() ) );
+	    return t;
         }
         else version( Posix )
         {
@@ -1124,6 +1128,24 @@
         }
     }
 
+    /**
+     * Search the list of all threads for a thread with the given thread identifier
+     *
+     * Params:
+     *  addr = The thread identifier to search for
+     * Returns:
+     *  the thread object associated with the thread identifier, null if not found
+     */
+    static Thread findThread( ThreadAddr addr )
+    {
+        synchronized( slock )
+        {
+	    foreach( Thread t; Thread )
+		if( t.m_addr == addr )
+		    return t;
+	}
+	return null;
+    }
 
     /**
      * Operates on all threads currently being tracked by the system.  The
@@ -1478,6 +1500,14 @@
     // Add a context to the global context list.
     //
     static void add( Context* c )
+    {
+        synchronized( slock )
+        {
+	    add_nolock( c );
+	}
+    }
+
+    static void add_nolock( Context* c )
     in
     {
         assert( c );
@@ -1485,16 +1515,13 @@
     }
     body
     {
-        synchronized( slock )
+        if( sm_cbeg )
         {
-            if( sm_cbeg )
-            {
-                c.next = sm_cbeg;
-                sm_cbeg.prev = c;
-            }
-            sm_cbeg = c;
-            ++sm_clen;
+            c.next = sm_cbeg;
+            sm_cbeg.prev = c;
         }
+        sm_cbeg = c;
+        ++sm_clen;
     }
 
 
@@ -1537,6 +1564,14 @@
     // Add a thread to the global thread list.
     //
     static void add( Thread t )
+    {
+        synchronized( slock )
+	{
+	    add_nolock( t );
+	}
+    }
+
+    static void add_nolock( Thread t )
     in
     {
         assert( t );
@@ -1545,16 +1580,13 @@
     }
     body
     {
-        synchronized( slock )
+	if( sm_tbeg )
         {
-            if( sm_tbeg )
-            {
-                t.next = sm_tbeg;
-                sm_tbeg.prev = t;
-            }
-            sm_tbeg = t;
-            ++sm_tlen;
+            t.next = sm_tbeg;
+            sm_tbeg.prev = t;
         }
+        sm_tbeg = t;
+        ++sm_tlen;
     }
 
 
@@ -1566,10 +1598,12 @@
     {
         assert( t );
         assert( t.next || t.prev );
-        version( Windows )
+        version( none )
         {
             // NOTE: This doesn't work for Posix as m_isRunning must be set to
             //       false after the thread is removed during normal execution.
+            // NOTE: This doesn't work for Windows either because remove is called
+	    //       from the thread itself
             assert( !t.isRunning );
         }
     }
@@ -1693,44 +1727,90 @@
  */
 extern (C) void thread_attachThis()
 {
+    synchronized( Thread.slock )
+    {
+	version( Windows )
+	{
+	    Thread thisThread = thread_attach_nolock( GetCurrentThreadId(), getStackBottom() );
+	}
+	else version( Posix )
+	{
+	    Thread thisThread = thread_attach_nolock( pthread_self(), getStackBottom() );
+	}
+	Thread.setThis( thisThread );
+    }
+}
+
+/**
+ * Registers the thread with the given identifier for use with the D Runtime.  If this routine
+ * is called for a thread which is already registered, the result is undefined.
+ */
+extern (C) Thread thread_attach( Thread.ThreadAddr addr )
+{
+    synchronized( Thread.slock )
+    {
+	version( Windows )
+	{
+	    void* bstack = getThreadStackBottom( addr );
+	}
+	else version( Posix )
+	{
+	    void* bstack = null;
+	    assert( false ); // not implemented
+	}
+	return thread_attach_nolock( addr, bstack );
+	// setThis cannot be called, because it sets the value in the current thread, 
+	//  not in the thread ew just attached to
+    }
+}
+
+extern (C) Thread thread_attach_nolock( Thread.ThreadAddr addr, void* bstack )
+{
+    // the gc should not be touched before attaching to the thread, because
+    //  it might interfere with threads that use the GC, but won't suspend
+    //  this thread. So we use a Thread object created by an attached thread.
+    // This is not necessary for the main (first) thread, because there is no
+    // concurrent thread.
+    static Thread nextThread;
+    Thread thisThread = nextThread ? nextThread : new Thread();
+
     version( Windows )
     {
-        Thread          thisThread  = new Thread();
-        Thread.Context* thisContext = &thisThread.m_main;
-        assert( thisContext == thisThread.m_curr );
+	Thread.Context* thisContext = &thisThread.m_main;
+	assert( thisContext == thisThread.m_curr );
 
-        thisThread.m_addr  = GetCurrentThreadId();
-        thisThread.m_hndl  = GetCurrentThreadHandle();
-        thisContext.bstack = getStackBottom();
-        thisContext.tstack = thisContext.bstack;
+	thisThread.m_addr  = addr;
+	thisThread.m_hndl  = addr == GetCurrentThreadId() ? GetCurrentThreadHandle() : OpenThreadHandle( addr );
+	thisContext.bstack = bstack;
+	thisContext.tstack = thisContext.bstack;
 
-        thisThread.m_isDaemon = true;
-
-        Thread.setThis( thisThread );
+	thisThread.m_isDaemon = true;
     }
     else version( Posix )
     {
-        Thread          thisThread  = new Thread();
-        Thread.Context* thisContext = thisThread.m_curr;
-        assert( thisContext == &thisThread.m_main );
+	Thread.Context* thisContext = thisThread.m_curr;
+	assert( thisContext == &thisThread.m_main );
 
-        thisThread.m_addr  = pthread_self();
-        thisContext.bstack = getStackBottom();
-        thisContext.tstack = thisContext.bstack;
+	thisThread.m_addr  = addr;
+	thisContext.bstack = bstack;
+	thisContext.tstack = thisContext.bstack;
 
-        thisThread.m_isRunning = true;
-        thisThread.m_isDaemon  = true;
-
-        Thread.setThis( thisThread );
+	thisThread.m_isRunning = true;
+	thisThread.m_isDaemon  = true;
     }
     version( OSX )
     {
-        thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
-        assert( thisThread.m_tmach != thisThread.m_tmach.init );
-    }    
+	thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
+	assert( thisThread.m_tmach != thisThread.m_tmach.init );
+    }
 
-    Thread.add( thisThread );
-    Thread.add( thisContext );
+    Thread.add_nolock( thisThread );
+    Thread.add_nolock( thisContext );
+
+    // Now it is safe to alloc anything from the GC
+    nextThread = new Thread();
+
+    return thisThread;
 }
 
 
@@ -1743,7 +1823,18 @@
     Thread.remove( Thread.getThis() );
 }
 
+/**
+ * Deregisters the thread with the given thread identifier from use with the runtime.
+ * If this routine is called for a thread which is not registered, it does nothing.
+ */
+extern (C) void thread_detach( Thread.ThreadAddr addr )
+{
+    Thread t = Thread.findThread( addr );
+    if( t )
+	Thread.remove( t );
+}
 
+
 /**
  * Joins all non-daemon threads that are currently running.  This is done by
  * performing successive scans through the thread list until a scan consists
@@ -1791,7 +1882,6 @@
 // Used for needLock below.
 private __gshared bool multiThreadedFlag = false;
 
-
 /**
  * This function is used to determine whether the the process is
  * multi-threaded.  Optimizations may only be performed on this
@@ -1806,6 +1896,12 @@
     return multiThreadedFlag;
 }
 
+// a DLL needs to set multiThreadedFlag, because threads might be
+//  created from other parts of the program that are not under our control
+extern (C) void thread_setNeedLock(bool need) nothrow
+{
+    multiThreadedFlag = need;
+}
 
 // Used for suspendAll/resumeAll below.
 private __gshared uint suspendDepth = 0;
Index: src/core/thread_helper.d
===================================================================
--- src/core/thread_helper.d	(revision 0)
+++ src/core/thread_helper.d	(revision 0)
@@ -0,0 +1,165 @@
+/**
+ * This module provides OS specific helper function for threads support
+ */
+
+module core.thread_helper;
+
+version( Windows )
+{
+    import std.c.windows.windows;
+    import std.c.stdlib;
+
+    public import core.thread;
+
+    ///////////////////////////////////////////////////////////////////
+
+    const SystemProcessInformation = 5;
+    const STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
+
+    // abbreviated versions of these structs
+    struct _SYSTEM_PROCESS_INFORMATION
+    {
+	int NextEntryOffset; // When this entry is 0, there are no more processes to be read.
+	int NumberOfThreads;
+	int[15] fill1;
+	int ProcessId;
+	int[28] fill2;
+    
+	// SYSTEM_THREAD_INFORMATION or SYSTEM_EXTENDED_THREAD_INFORMATION structures follow.
+    }
+
+    struct _SYSTEM_THREAD_INFORMATION
+    {
+	int[8] fill1;
+	int ProcessId;
+	int ThreadId;
+	int[6] fill2;
+    }
+
+    alias extern(Windows)
+    HRESULT fnNtQuerySystemInformation( uint SystemInformationClass, void* info, uint infoLength, uint* ReturnLength );
+
+    const ThreadBasicInformation = 0;
+
+    struct THREAD_BASIC_INFORMATION 
+    {
+	int    ExitStatus;
+	void** TebBaseAddress;
+	int    ProcessId;
+	int    ThreadId;
+	int    AffinityMask;
+	int    Priority;
+	int    BasePriority;
+    }
+
+    alias extern(Windows)
+    int fnNtQueryInformationThread( HANDLE ThreadHandle, uint ThreadInformationClass, void* buf, uint size, uint* ReturnLength );
+
+    ///////////////////////////////////////////////////////////////////
+    // support attaching to thread other than just executing
+    void** getTEB( HANDLE hnd )
+    {
+	HANDLE nthnd = GetModuleHandleA( "NTDLL" );
+	assert( nthnd, "cannot get module handle for ntdll" );
+	fnNtQueryInformationThread* fn = cast(fnNtQueryInformationThread*) GetProcAddress( nthnd, "NtQueryInformationThread" );
+	assert( fn, "cannot find NtQueryInformationThread in ntdll" );
+
+	THREAD_BASIC_INFORMATION tbi;
+	int Status = (*fn)(hnd, ThreadBasicInformation, &tbi, tbi.sizeof, null);
+	assert(Status == 0);
+	
+	return tbi.TebBaseAddress;
+    }
+
+    extern(Windows)
+    HANDLE OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
+
+    const SYNCHRONIZE = 0x00100000;
+    const THREAD_GET_CONTEXT = 8;
+    const THREAD_QUERY_INFORMATION = 0x40;
+    const THREAD_SUSPEND_RESUME = 2;
+
+    void** getTEB( uint id )
+    {
+	HANDLE hnd = OpenThread( THREAD_QUERY_INFORMATION, FALSE, id );
+	assert( hnd, "OpenThread failed" );
+
+	void** teb = getTEB( hnd );
+	CloseHandle( hnd );
+	return teb;
+    }
+
+    void* getThreadStackBottom( HANDLE hnd )
+    {
+	void** teb = getTEB( hnd );
+	return teb[1];
+    }
+
+    void* getThreadStackBottom( uint id )
+    {
+	void** teb = getTEB( id );
+	return teb[1];
+    }
+
+    HANDLE OpenThreadHandle( uint id )
+    {
+	return OpenThread( SYNCHRONIZE|THREAD_GET_CONTEXT|THREAD_QUERY_INFORMATION|THREAD_SUSPEND_RESUME, FALSE, id );
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // support attaching to all running threads
+    // using unction instead of delegate here to avoid allocating closure
+    bool enumProcessThreads( uint procid, bool function( uint id, void* context ) dg, void* context )
+    {
+	HANDLE hnd = GetModuleHandleA( "NTDLL" );
+	fnNtQuerySystemInformation* fn = cast(fnNtQuerySystemInformation*) GetProcAddress( hnd, "NtQuerySystemInformation" );
+	if( !fn )
+	    return false;
+
+	uint sz = 16384;
+	uint retLength;
+	HRESULT rc;
+	char* buf;
+	for( ; ; )
+	{
+	    buf = cast(char*) std.c.stdlib.malloc(sz);
+	    if(!buf)
+	    	return false;
+	    rc = (*fn)( SystemProcessInformation, buf, sz, &retLength );
+	    if( rc != STATUS_INFO_LENGTH_MISMATCH )
+		break;
+	    std.c.stdlib.free( buf );
+	    sz *= 2;
+	}
+	scope(exit) std.c.stdlib.free( buf );
+
+	if(rc != 0)
+	    return false;
+
+	auto pinfo = cast(_SYSTEM_PROCESS_INFORMATION*) buf;
+	auto pend  = cast(_SYSTEM_PROCESS_INFORMATION*) (buf + retLength);
+	for( ; pinfo < pend; )
+	{
+	    if( pinfo.ProcessId == procid )
+	    {
+		auto tinfo = cast(_SYSTEM_THREAD_INFORMATION*)(pinfo + 1);
+		for( int i = 0; i < pinfo.NumberOfThreads; i++, tinfo++ )
+		    if( tinfo.ProcessId == procid )
+			if( !dg( tinfo.ThreadId, context ) )
+			    return false;
+	    }
+	    if( pinfo.NextEntryOffset == 0 )
+		break;
+	    pinfo = cast(_SYSTEM_PROCESS_INFORMATION*) (cast(char*) pinfo + pinfo.NextEntryOffset);
+	}
+	return true;
+    }
+
+    bool enumProcessThreads( bool function( uint id, void* context ) dg, void* context )
+    {
+	return enumProcessThreads( GetCurrentProcessId(), dg, context );
+    }
+
+
+}
+
Index: win32.mak
===================================================================
--- win32.mak	(revision 255)
+++ win32.mak	(working copy)
@@ -96,6 +96,8 @@
 	src/core/sync/rwmutex.d \
 	src/core/sync/semaphore.d \
 	src/core/thread.d \
+	src/core/thread_helper.d \
+	src/core/dll_helper.d \
 	src/core/threadasm.S \
 	src/core/vararg.d \
 	src/object_.d \
@@ -192,6 +194,8 @@
 	src\core\memory.d \
 	src\core\runtime.d \
 	src\core\thread.d \
+	src\core\thread_helper.d \
+	src\core\dll_helper.d \
 	src\core\vararg.d \
 	\
 	src\core\sync\barrier.d \
