Implement OpenThread() winapi call.
Implement a few pthreads functions.

diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec
index 922f8fa..ba07c8e 100644
--- a/dlls/kernel/kernel32.spec
+++ b/dlls/kernel/kernel32.spec
@@ -594,6 +594,7 @@
 @ stub OpenProfileUserMapping
 @ stdcall OpenSemaphoreA(long long str) OpenSemaphoreA
 @ stdcall OpenSemaphoreW(long long wstr) OpenSemaphoreW
+@ stdcall OpenThread(long long long) OpenThread
 @ stdcall OpenVxDHandle(long) OpenVxDHandle
 @ stdcall OutputDebugStringA(str) OutputDebugStringA
 @ stdcall OutputDebugStringW(wstr) OutputDebugStringW
@@ -963,8 +964,8 @@
 @ stdcall GetSystemWindowsDirectoryA(ptr long) GetSystemWindowsDirectoryA
 @ stdcall GetSystemWindowsDirectoryW(ptr long) GetSystemWindowsDirectoryW
 @ stdcall InitializeCriticalSectionAndSpinCount(ptr long) InitializeCriticalSectionAndSpinCount
-@ stdcall SetCriticalSectionSpinCount(ptr long) SetCriticalSectionSpinCount
 @ stdcall ProcessIdToSessionId(long ptr) ProcessIdToSessionId
+@ stdcall SetCriticalSectionSpinCount(ptr long) SetCriticalSectionSpinCount
 @ stdcall GetCalendarInfoA(long long long ptr long ptr) GetCalendarInfoA
 @ stdcall GetCalendarInfoW(long long long ptr long ptr) GetCalendarInfoW
 @ stdcall SetCalendarInfoA(long long long str) SetCalendarInfoA
diff --git a/include/winbase.h b/include/winbase.h
index e92ea92..038ee1e 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1328,23 +1328,24 @@
 HANDLE      WINAPI OpenBackupEventLogA(LPCSTR,LPCSTR);
 HANDLE      WINAPI OpenBackupEventLogW(LPCWSTR,LPCWSTR);
 #define     OpenBackupEventLog WINELIB_NAME_AW(OpenBackupEventLog)
-HANDLE    WINAPI OpenEventA(DWORD,BOOL,LPCSTR);
-HANDLE    WINAPI OpenEventW(DWORD,BOOL,LPCWSTR);
+HANDLE      WINAPI OpenEventA(DWORD,BOOL,LPCSTR);
+HANDLE      WINAPI OpenEventW(DWORD,BOOL,LPCWSTR);
 #define     OpenEvent WINELIB_NAME_AW(OpenEvent)
 HANDLE      WINAPI OpenEventLogA(LPCSTR,LPCSTR);
 HANDLE      WINAPI OpenEventLogW(LPCWSTR,LPCWSTR);
 #define     OpenEventLog WINELIB_NAME_AW(OpenEventLog)
-HANDLE    WINAPI OpenFileMappingA(DWORD,BOOL,LPCSTR);
-HANDLE    WINAPI OpenFileMappingW(DWORD,BOOL,LPCWSTR);
+HANDLE      WINAPI OpenFileMappingA(DWORD,BOOL,LPCSTR);
+HANDLE      WINAPI OpenFileMappingW(DWORD,BOOL,LPCWSTR);
 #define     OpenFileMapping WINELIB_NAME_AW(OpenFileMapping)
-HANDLE    WINAPI OpenMutexA(DWORD,BOOL,LPCSTR);
-HANDLE    WINAPI OpenMutexW(DWORD,BOOL,LPCWSTR);
+HANDLE      WINAPI OpenMutexA(DWORD,BOOL,LPCSTR);
+HANDLE      WINAPI OpenMutexW(DWORD,BOOL,LPCWSTR);
 #define     OpenMutex WINELIB_NAME_AW(OpenMutex)
-HANDLE    WINAPI OpenProcess(DWORD,BOOL,DWORD);
+HANDLE      WINAPI OpenProcess(DWORD,BOOL,DWORD);
 BOOL        WINAPI OpenProcessToken(HANDLE,DWORD,PHANDLE);
-HANDLE    WINAPI OpenSemaphoreA(DWORD,BOOL,LPCSTR);
-HANDLE    WINAPI OpenSemaphoreW(DWORD,BOOL,LPCWSTR);
+HANDLE      WINAPI OpenSemaphoreA(DWORD,BOOL,LPCSTR);
+HANDLE      WINAPI OpenSemaphoreW(DWORD,BOOL,LPCWSTR);
 #define     OpenSemaphore WINELIB_NAME_AW(OpenSemaphore)
+HANDLE      WINAPI OpenThread(DWORD,BOOL,DWORD);
 BOOL        WINAPI OpenThreadToken(HANDLE,DWORD,BOOL,PHANDLE);
 HANDLE      WINAPI OpenWaitableTimerA(DWORD,BOOL,LPCSTR);
 HANDLE      WINAPI OpenWaitableTimerW(DWORD,BOOL,LPCWSTR);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index d9a3796..3d4e5a1 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -573,6 +573,21 @@
 
 
 
+struct open_thread_request
+{
+    struct request_header __header;
+    void*        tid;
+    unsigned int access;
+    int          inherit;
+};
+struct open_thread_reply
+{
+    struct reply_header __header;
+    handle_t     handle;
+};
+
+
+
 struct select_request
 {
     struct request_header __header;
@@ -2717,6 +2732,7 @@
     REQ_set_handle_info,
     REQ_dup_handle,
     REQ_open_process,
+    REQ_open_thread,
     REQ_select,
     REQ_create_event,
     REQ_event_op,
@@ -2877,6 +2893,7 @@
     struct set_handle_info_request set_handle_info_request;
     struct dup_handle_request dup_handle_request;
     struct open_process_request open_process_request;
+    struct open_thread_request open_thread_request;
     struct select_request select_request;
     struct create_event_request create_event_request;
     struct event_op_request event_op_request;
@@ -3035,6 +3052,7 @@
     struct set_handle_info_reply set_handle_info_reply;
     struct dup_handle_reply dup_handle_reply;
     struct open_process_reply open_process_reply;
+    struct open_thread_reply open_thread_reply;
     struct select_reply select_reply;
     struct create_event_reply create_event_reply;
     struct event_op_reply event_op_reply;
@@ -3166,6 +3184,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 76
+#define SERVER_PROTOCOL_VERSION 77
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/scheduler/pthread.c b/scheduler/pthread.c
index a81ab27..404f562 100644
--- a/scheduler/pthread.c
+++ b/scheduler/pthread.c
@@ -124,6 +124,100 @@
 {
 }
 
+struct pthread_thread_init {
+	 void* (*start_routine)(void*);
+	 void* arg;
+}; 
+
+static DWORD CALLBACK pthread_thread_start(LPVOID data)
+{
+  struct pthread_thread_init init = *(struct pthread_thread_init*)data; 
+  HeapFree(GetProcessHeap(),0,data);
+  return (DWORD)init.start_routine(init.arg);
+}
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*
+        (*start_routine)(void *), void* arg)
+{
+  HANDLE hThread;
+  struct pthread_thread_init* idata = HeapAlloc(GetProcessHeap(), 0, 
+		sizeof(struct pthread_thread_init));
+
+  idata->start_routine = start_routine; 
+  idata->arg = arg;
+  hThread = CreateThread(NULL, 0, pthread_thread_start, idata, 0, thread);
+
+  if(hThread)
+    CloseHandle(hThread);
+  else
+  {
+    HeapFree(GetProcessHeap(),0,idata); /* free idata struct on failure */
+    return EAGAIN;
+  }
+ 
+  return 0;
+}
+ 
+int pthread_cancel(pthread_t thread)
+{
+  HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread);
+    
+  if(!TerminateThread(hThread, 0))
+  {
+    CloseHandle(hThread);
+    return EINVAL;      /* return error */
+  }
+ 
+  CloseHandle(hThread);
+ 
+  return 0;             /* return success */
+}   
+
+int pthread_join(pthread_t thread, void **value_ptr)
+{
+  HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread);
+ 
+  WaitForSingleObject(hThread, INFINITE);
+  if(!GetExitCodeThread(hThread, (LPDWORD)value_ptr))
+  {
+    CloseHandle(hThread);
+    return EINVAL; /* FIXME: make this more correctly match */
+  }                /* windows errors */
+
+  CloseHandle(hThread);
+  return 0;
+}   
+
+/*FIXME: not sure what to do with this one... */
+int pthread_detach(pthread_t thread)
+{
+  P_OUTPUT("FIXME:pthread_detach\n");
+  return 0;
+}
+
+/* FIXME: we have no equivalents in win32 for the policys */
+/* so just keep this as a stub */
+int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
+{
+  P_OUTPUT("FIXME:pthread_attr_setschedpolicy\n");
+  return 0;
+}
+
+/* FIXME: no win32 equivalent for scope */
+int pthread_attr_setscope(pthread_attr_t *attr, int scope)
+{
+  P_OUTPUT("FIXME:pthread_attr_setscope\n");
+  return 0; /* return success */
+}
+  
+/* FIXME: no win32 equivalent for schedule param */
+int pthread_attr_setschedparam(pthread_attr_t *attr,
+    const struct sched_param *param)
+{
+  P_OUTPUT("FIXME:pthread_attr_setschedparam\n");
+  return 0; /* return success */
+}
+
 int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
 {
   static pthread_once_t the_once = PTHREAD_ONCE_INIT;
diff --git a/scheduler/thread.c b/scheduler/thread.c
index aabee10..3df0807 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -382,6 +382,25 @@
     }
 }
 
+/***********************************************************************
+ * OpenThread Retrieves a handle to a thread from its thread id
+ *
+ * RETURNS
+ *    None
+ */
+HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
+{
+    HANDLE ret = 0;
+    SERVER_START_REQ( open_thread )
+    {
+        req->tid     = (void *)dwThreadId;
+        req->access  = dwDesiredAccess;
+        req->inherit = bInheritHandle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
+    }
+    SERVER_END_REQ;
+    return ret;
+}
 
 /***********************************************************************
  * SetThreadContext [KERNEL32.@]  Sets context of thread.
diff --git a/server/protocol.def b/server/protocol.def
index 0cc3f26..a13fcc7 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -462,6 +462,16 @@
 @END
 
 
+/* Open a handle to a thread */
+@REQ(open_thread)
+    void*        tid;          /* thread id to open */
+    unsigned int access;       /* wanted access rights */
+    int          inherit;      /* inherit flag */
+@REPLY
+    handle_t     handle;       /* handle to the thread */
+@END
+
+
 /* Wait for handles */
 @REQ(select)
     int          flags;        /* wait flags (see below) */
diff --git a/server/request.h b/server/request.h
index 7e3b507..99bba36 100644
--- a/server/request.h
+++ b/server/request.h
@@ -125,6 +125,7 @@
 DECL_HANDLER(set_handle_info);
 DECL_HANDLER(dup_handle);
 DECL_HANDLER(open_process);
+DECL_HANDLER(open_thread);
 DECL_HANDLER(select);
 DECL_HANDLER(create_event);
 DECL_HANDLER(event_op);
@@ -284,6 +285,7 @@
     (req_handler)req_set_handle_info,
     (req_handler)req_dup_handle,
     (req_handler)req_open_process,
+    (req_handler)req_open_thread,
     (req_handler)req_select,
     (req_handler)req_create_event,
     (req_handler)req_event_op,
diff --git a/server/thread.c b/server/thread.c
index eba63e1..cf5dcf8 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -854,6 +854,19 @@
     }
 }
 
+/* open a handle to a thread */
+DECL_HANDLER(open_thread)
+{
+    struct thread *thread = get_thread_from_id( req->tid );
+
+    reply->handle = 0;
+    if (thread)
+    {
+        reply->handle = alloc_handle( current->process, thread, req->access, req->inherit );
+        release_object( thread );
+    }
+}
+
 /* fetch information about a thread */
 DECL_HANDLER(get_thread_info)
 {
diff --git a/server/trace.c b/server/trace.c
index a8844f1..cb2f19f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -638,6 +638,18 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
+static void dump_open_thread_request( const struct open_thread_request *req )
+{
+    fprintf( stderr, " tid=%p,", req->tid );
+    fprintf( stderr, " access=%08x,", req->access );
+    fprintf( stderr, " inherit=%d", req->inherit );
+}
+
+static void dump_open_thread_reply( const struct open_thread_reply *req )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+}
+
 static void dump_select_request( const struct select_request *req )
 {
     fprintf( stderr, " flags=%d,", req->flags );
@@ -2177,6 +2189,7 @@
     (dump_func)dump_set_handle_info_request,
     (dump_func)dump_dup_handle_request,
     (dump_func)dump_open_process_request,
+    (dump_func)dump_open_thread_request,
     (dump_func)dump_select_request,
     (dump_func)dump_create_event_request,
     (dump_func)dump_event_op_request,
@@ -2333,6 +2346,7 @@
     (dump_func)dump_set_handle_info_reply,
     (dump_func)dump_dup_handle_reply,
     (dump_func)dump_open_process_reply,
+    (dump_func)dump_open_thread_reply,
     (dump_func)0,
     (dump_func)dump_create_event_reply,
     (dump_func)0,
@@ -2489,6 +2503,7 @@
     "set_handle_info",
     "dup_handle",
     "open_process",
+    "open_thread",
     "select",
     "create_event",
     "event_op",