diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec index 922f8fa0db0..ba07c8e2aef 100644 --- a/dlls/kernel/kernel32.spec +++ b/dlls/kernel/kernel32.spec @@ -594,6 +594,7 @@ debug_channels (comm console debugstr dll int resource stress thunk toolhelp @ 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 @@ debug_channels (comm console debugstr dll int resource stress thunk toolhelp @ 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 e92ea92f7af..038ee1e9301 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1328,23 +1328,24 @@ BOOL WINAPI NotifyChangeEventLog(HANDLE,HANDLE); 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 d9a3796894b..3d4e5a15c5c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -573,6 +573,21 @@ struct open_process_reply +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 @@ enum request 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 @@ union generic_request 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 @@ union generic_reply 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 @@ union generic_reply 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 a81ab2703da..404f562e1a8 100644 --- a/scheduler/pthread.c +++ b/scheduler/pthread.c @@ -124,6 +124,100 @@ void __pthread_initialize(void) { } +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 aabee1053c5..3df08075505 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -382,6 +382,25 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ } } +/*********************************************************************** + * 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 0cc3f26d69f..a13fcc7a8b7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -462,6 +462,16 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC }; @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 7e3b5074c7e..99bba362098 100644 --- a/server/request.h +++ b/server/request.h @@ -125,6 +125,7 @@ DECL_HANDLER(close_handle); 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 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (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 eba63e18d84..cf5dcf87b9d 100644 --- a/server/thread.c +++ b/server/thread.c @@ -854,6 +854,19 @@ DECL_HANDLER(terminate_thread) } } +/* 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 a8844f1dd0f..cb2f19f03b3 100644 --- a/server/trace.c +++ b/server/trace.c @@ -638,6 +638,18 @@ static void dump_open_process_reply( const struct open_process_reply *req ) 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 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (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 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (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 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "set_handle_info", "dup_handle", "open_process", + "open_thread", "select", "create_event", "event_op",