Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/kernel32/tests/thread.c | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c index 6ccf7af85f8..9c58095fe01 100644 --- a/dlls/kernel32/tests/thread.c +++ b/dlls/kernel32/tests/thread.c @@ -100,6 +100,8 @@ static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG); static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *); static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **); +static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG,PVECTORED_EXCEPTION_HANDLER); +static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
static HANDLE create_target_process(const char *arg) { @@ -2351,6 +2353,23 @@ static void test_thread_info(void) CloseHandle(thread); }
+typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; /* Must be 0x1000. */ + LPCSTR szName; /* Pointer to name (in user addr space). */ + DWORD dwThreadID; /* Thread ID (-1 = caller thread). */ + DWORD dwFlags; /* Reserved for future use, must be zero. */ +} THREADNAME_INFO; + +static LONG CALLBACK msvc_threadname_vec_handler(EXCEPTION_POINTERS *ExceptionInfo) +{ + if (ExceptionInfo->ExceptionRecord != NULL && + ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_NAME_THREAD) + return EXCEPTION_CONTINUE_EXECUTION; + + return EXCEPTION_CONTINUE_SEARCH; +} + static void test_thread_description(void) { THREAD_NAME_INFORMATION *thread_desc; @@ -2360,6 +2379,9 @@ static void test_thread_description(void) char buff[128]; WCHAR *ptr; HRESULT hr; + HANDLE thread; + PVOID vectored_handler; + THREADNAME_INFO info;
if (!pGetThreadDescription) { @@ -2476,6 +2498,59 @@ static void test_thread_description(void) ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#x.\n", hr); ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr)); LocalFree(ptr); + + /* Get with only THREAD_QUERY_LIMITED_INFORMATION access. */ + thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId()); + + ptr = NULL; + hr = pGetThreadDescription(thread, &ptr); + ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#x.\n", hr); + ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr)); + LocalFree(ptr); + + len = 0; + status = pNtQueryInformationThread(thread, ThreadNameInformation, NULL, 0, &len); + ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#x.\n", status); + ok(len == sizeof(*thread_desc), "Unexpected structure length %u.\n", len); + + CloseHandle(thread); + + /* Set with only THREAD_SET_LIMITED_INFORMATION access. */ + thread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, GetCurrentThreadId()); + + hr = pSetThreadDescription(thread, desc); + todo_wine + ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr); + + ptr = NULL; + hr = pGetThreadDescription(GetCurrentThread(), &ptr); + ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#x.\n", hr); + todo_wine + ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr)); + LocalFree(ptr); + + CloseHandle(thread); + + /* The old exception-based thread name method should not affect GetThreadDescription. */ + hr = pSetThreadDescription(GetCurrentThread(), desc); + ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr); + + vectored_handler = pRtlAddVectoredExceptionHandler(FALSE, &msvc_threadname_vec_handler); + ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n"); + + info.dwType = 0x1000; + info.szName = "123"; + info.dwThreadID = -1; + info.dwFlags = 0; + RaiseException(EXCEPTION_WINE_NAME_THREAD, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + + pRtlRemoveVectoredExceptionHandler(vectored_handler); + + ptr = NULL; + hr = pGetThreadDescription(GetCurrentThread(), &ptr); + ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#x.\n", hr); + ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr)); + LocalFree(ptr); }
static void init_funcs(void) @@ -2524,6 +2599,8 @@ static void init_funcs(void) X(NtQueryInformationThread); X(RtlGetThreadErrorMode); X(NtSetInformationThread); + X(RtlAddVectoredExceptionHandler); + X(RtlRemoveVectoredExceptionHandler); } #undef X }
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/kernel32/tests/thread.c | 2 -- server/thread.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c index 9c58095fe01..dde0c6cec04 100644 --- a/dlls/kernel32/tests/thread.c +++ b/dlls/kernel32/tests/thread.c @@ -2519,13 +2519,11 @@ static void test_thread_description(void) thread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
hr = pSetThreadDescription(thread, desc); - todo_wine ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr);
ptr = NULL; hr = pGetThreadDescription(GetCurrentThread(), &ptr); ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#x.\n", hr); - todo_wine ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr)); LocalFree(ptr);
diff --git a/server/thread.c b/server/thread.c index 467ccd1f0db..ede64087e91 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1533,8 +1533,10 @@ DECL_HANDLER(get_thread_times) DECL_HANDLER(set_thread_info) { struct thread *thread; + unsigned int access = (req->mask == SET_THREAD_INFO_DESCRIPTION) ? THREAD_SET_LIMITED_INFORMATION + : THREAD_SET_INFORMATION;
- if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION ))) + if ((thread = get_thread_from_handle( req->handle, access ))) { set_thread_info( thread, req ); release_object( thread );