applied Serguei Narojnyi's patch to add native thread support on the Win32

* threads.c: applied Serguei Narojnyi's patch to add native
  thread support on the Win32 platform
* testThreadsWin32.c Makefile.am: added the test program also
  from Serguei, Win32 specific
* include/win32config.h include/libxml/xmlwin32version.h.in:
  added patch from Igor for the Windows thread specific defines.
Daniel
diff --git a/threads.c b/threads.c
index be3b131..dc69f47 100644
--- a/threads.c
+++ b/threads.c
@@ -26,6 +26,12 @@
 #ifdef HAVE_PTHREAD_H
 #include <pthread.h>
 #endif
+#ifdef HAVE_WIN32_THREADS
+#include <windows.h>
+#ifndef _MSC_VER
+#include <process.h>
+#endif
+#endif
 
 #if defined(SOLARIS)
 #include <note.h>
@@ -45,6 +51,8 @@
 struct _xmlMutex {
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_t lock;
+#elif defined HAVE_WIN32_THREADS
+	HANDLE mutex;
 #else
     int empty;
 #endif
@@ -60,6 +68,9 @@
     unsigned int    waiters;
     pthread_t       tid;
     pthread_cond_t  cv;
+#elif defined HAVE_WIN32_THREADS
+	CRITICAL_SECTION cs;
+	unsigned int count;
 #else
     int empty;
 #endif
@@ -74,7 +85,16 @@
 static pthread_key_t	globalkey;
 static pthread_t	mainthread;
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-#endif
+#elif defined HAVE_WIN32_THREADS
+#ifdef _MSC_VER
+static __declspec (thread) xmlGlobalState tlstate;
+static __declspec (thread) int tlstate_inited = 0;
+#else
+static DWORD globalkey;
+#endif /* _MSC_VER */
+static DWORD mainthread;
+static int run_once_init = 1;
+#endif /* HAVE_WIN32_THREADS */
 static xmlRMutexPtr	xmlLibraryLock = NULL;
 static void xmlOnceInit(void);
 
@@ -95,6 +115,8 @@
         return (NULL);
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_init(&tok->lock, NULL);
+#elif defined HAVE_WIN32_THREADS
+	tok->mutex = CreateMutex (NULL, FALSE, NULL);
 #endif
     return (tok);
 }
@@ -111,6 +133,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_destroy(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	CloseHandle (tok->mutex);
 #endif
     free(tok);
 }
@@ -126,6 +150,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_lock(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	WaitForSingleObject (tok->mutex, INFINITE);
 #endif
 
 }
@@ -141,6 +167,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_unlock(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	ReleaseMutex (tok->mutex);
 #endif
 }
 
@@ -165,6 +193,9 @@
     pthread_mutex_init(&tok->lock, NULL);
     tok->held = 0;
     tok->waiters = 0;
+#elif defined HAVE_WIN32_THREADS
+	InitializeCriticalSection (&tok->cs);
+	tok->count = 0;
 #endif
     return (tok);
 }
@@ -181,6 +212,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     pthread_mutex_destroy(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	DeleteCriticalSection (&tok->cs);
 #endif
     free(tok);
 }
@@ -211,6 +244,9 @@
     tok->tid = pthread_self();
     tok->held = 1;
     pthread_mutex_unlock(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	EnterCriticalSection (&tok->cs);
+	++tok->count;
 #endif
 }
 
@@ -232,6 +268,8 @@
         tok->tid = 0;
     }
     pthread_mutex_unlock(&tok->lock);
+#elif defined HAVE_WIN32_THREADS
+	if (!--tok->count) LeaveCriticalSection (&tok->cs);
 #endif
 }
 
@@ -242,6 +280,7 @@
  ************************************************************************/
 
 #ifdef LIBXML_THREAD_ENABLED
+#ifndef _MSC_VER
 /**
  * xmlFreeGlobalState:
  * @state:  a thread global state
@@ -277,6 +316,7 @@
     xmlInitializeGlobalState(gs);
     return (gs);
 }
+#endif /* _MSC_VER */
 #endif /* LIBXML_THREAD_ENABLED */
 
 
@@ -287,6 +327,27 @@
  *
  * Returns the thread global state or NULL in case of error
  */
+
+#ifdef HAVE_WIN32_THREADS
+#ifndef _MSC_VER
+typedef struct _xmlGlobalStateCleanupHelperParams
+{
+	HANDLE thread;
+	void *memory;
+} xmlGlobalStateCleanupHelperParams;
+
+void __cdecl xmlGlobalStateCleanupHelper (void *p)
+{
+	xmlGlobalStateCleanupHelperParams *params = (xmlGlobalStateCleanupHelperParams *) p;
+	WaitForSingleObject (params->thread, INFINITE);
+	CloseHandle (params->thread);
+	xmlFreeGlobalState (params->memory);
+	free (params);
+	_endthread ();
+}
+#endif /* _MSC_VER */
+#endif /* HAVE_WIN32_THREADS */
+
 xmlGlobalStatePtr
 xmlGetGlobalState(void)
 {
@@ -303,12 +364,40 @@
         return (tsd);
     }
     return (globalval);
+#elif defined HAVE_WIN32_THREADS
+#ifdef _MSC_VER
+	if (!tlstate_inited)
+	{
+		tlstate_inited = 1;
+		xmlInitializeGlobalState (&tlstate);
+	}
+
+	return &tlstate;
+#else /* !_MSC_VER */
+	xmlGlobalState *globalval;
+
+	if (run_once_init) { run_once_init = 0; xmlOnceInit (); }
+
+	if ((globalval = (xmlGlobalState *) TlsGetValue (globalkey)) == NULL)
+	{
+		xmlGlobalState *tsd = xmlNewGlobalState();
+		xmlGlobalStateCleanupHelperParams *p = (xmlGlobalStateCleanupHelperParams *) malloc (sizeof (xmlGlobalStateCleanupHelperParams));
+
+		p->memory = tsd;
+		DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), GetCurrentProcess (), &p->thread, 0, TRUE, DUPLICATE_SAME_ACCESS);
+
+		TlsSetValue (globalkey, tsd);
+		_beginthread (xmlGlobalStateCleanupHelper, 0, p);
+
+		return (tsd);
+	}
+	return (globalval);
+#endif /* _MSC_VER */
 #else
     return(NULL);
 #endif
 }
 
-
 /************************************************************************
  *									*
  *			Library wide thread interfaces			*
@@ -327,6 +416,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     return((int) pthread_self());
+#elif defined HAVE_WIN32_THREADS
+	return GetCurrentThreadId ();
 #else
     return((int) 0);
 #endif
@@ -344,6 +435,8 @@
 {
 #ifdef HAVE_PTHREAD_H
     pthread_once(&once_control, xmlOnceInit);
+#elif defined HAVE_WIN32_THREADS
+	if (run_once_init) { run_once_init = 0; xmlOnceInit (); }
 #endif
         
 #ifdef DEBUG_THREADS
@@ -351,6 +444,8 @@
 #endif
 #ifdef HAVE_PTHREAD_H
     return(mainthread == pthread_self());
+#elif defined HAVE_WIN32_THREADS
+	return (mainthread == GetCurrentThreadId ());
 #else
     return(1);
 #endif
@@ -428,5 +523,10 @@
 #ifdef HAVE_PTHREAD_H
    (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
     mainthread = pthread_self();
+#elif defined HAVE_WIN32_THREADS
+#ifndef _MSC_VER
+	globalkey = TlsAlloc ();
+#endif /* _MSC_VER */
+	mainthread = GetCurrentThreadId ();
 #endif
 }