Nikolay Sivov : kernel32/tests: Add some tests for thread description API.

Alexandre Julliard julliard at winehq.org
Mon Nov 25 16:41:55 CST 2019


Module: wine
Branch: master
Commit: 602eb52ce9bdd1962fe1690a5fc40642144a8e06
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=602eb52ce9bdd1962fe1690a5fc40642144a8e06

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Nov 24 20:34:20 2019 +0300

kernel32/tests: Add some tests for thread description API.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/thread.c | 132 +++++++++++++++++++++++++++++++++++++++++++
 include/winternl.h           |   9 ++-
 2 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index ddbbec93ad..180eed8241 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -105,6 +105,8 @@ static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID
 static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
 static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
 static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
+static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *);
+static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **);
 
 static HANDLE create_target_process(const char *arg)
 {
@@ -2111,6 +2113,133 @@ todo_wine
     CloseHandle(thread);
 }
 
+static void test_thread_description(void)
+{
+    THREAD_DESCRIPTION_INFORMATION *thread_desc;
+    static const WCHAR *desc = L"thread_desc";
+    ULONG len, len2, desc_len;
+    NTSTATUS status;
+    char buff[128];
+    WCHAR *ptr;
+    HRESULT hr;
+
+    if (!pGetThreadDescription)
+    {
+        skip("Thread description API is not supported.\n");
+        return;
+    }
+
+    desc_len = lstrlenW(desc) * sizeof(*desc);
+    thread_desc = (THREAD_DESCRIPTION_INFORMATION *)buff;
+
+    /* Initial description. */
+    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, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
+    LocalFree(ptr);
+
+    len = 0;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, 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);
+
+    len2 = 0;
+    thread_desc->Length = 1;
+    thread_desc->Description = (WCHAR *)thread_desc;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, len, &len2);
+    ok(!status, "Failed to get thread info, status %#x.\n", status);
+    ok(len2 == sizeof(*thread_desc), "Unexpected structure length %u.\n", len);
+    ok(!thread_desc->Length, "Unexpected description length %#x.\n", thread_desc->Length);
+    ok(thread_desc->Description == (WCHAR *)(thread_desc + 1), "Unexpected description string pointer %p, %p.\n",
+            thread_desc->Description, thread_desc);
+
+    hr = pSetThreadDescription(GetCurrentThread(), NULL);
+    ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr);
+
+    hr = pSetThreadDescription(GetCurrentThread(), desc);
+    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);
+    ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
+    LocalFree(ptr);
+
+    len = 0;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, NULL, 0, &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "Failed to get thread info, status %#x.\n", status);
+    ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
+
+    len = 0;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, buff, sizeof(buff), &len);
+    ok(!status, "Failed to get thread info.\n");
+    ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
+
+    ok(thread_desc->Length == (desc_len << 16 | desc_len), "Unexpected description length %#x.\n",
+            thread_desc->Length);
+    ok(thread_desc->Description == (WCHAR *)(thread_desc + 1), "Unexpected description string pointer %p, %p.\n",
+            thread_desc->Description, thread_desc);
+    ok(!memcmp(thread_desc->Description, desc, desc_len), "Unexpected description string.\n");
+
+    /* Partial results. */
+    len = 0;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, NULL, 0, &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#x.\n", status);
+    ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
+
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, buff, len - sizeof(WCHAR), &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#x.\n", status);
+    ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
+
+    /* Change description. */
+    thread_desc->Length = 8 << 16 | 8;
+    lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
+
+    status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
+    ok(status == STATUS_SUCCESS, "Failed to set thread description, status %#x.\n", status);
+
+    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, L"desc"), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
+    LocalFree(ptr);
+
+    status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc) - 1);
+    ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#x.\n", status);
+
+    status = NtSetInformationThread(GetCurrentThread(), ThreadDescription, NULL, sizeof(*thread_desc));
+    ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#x.\n", status);
+
+    thread_desc->Description = NULL;
+    status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
+    ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#x.\n", status);
+
+    hr = pSetThreadDescription(GetCurrentThread(), NULL);
+    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);
+    ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
+    LocalFree(ptr);
+
+    /* Set with 0 length/NULL pointer. */
+    hr = pSetThreadDescription(GetCurrentThread(), L"123");
+    ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr);
+
+    thread_desc->Length = 0;
+    thread_desc->Description = NULL;
+    status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
+    ok(!status, "Failed to set thread description, status %#x.\n", status);
+
+    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, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
+    LocalFree(ptr);
+}
+
 static void init_funcs(void)
 {
     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
@@ -2147,6 +2276,8 @@ static void init_funcs(void)
 
     X(GetThreadGroupAffinity);
     X(SetThreadGroupAffinity);
+    X(SetThreadDescription);
+    X(GetThreadDescription);
 
     X(FlsAlloc);
     X(FlsFree);
@@ -2223,6 +2354,7 @@ START_TEST(thread)
    test_ThreadErrorMode();
    test_thread_fpu_cw();
    test_thread_actctx();
+   test_thread_description();
 
    test_threadpool();
 }
diff --git a/include/winternl.h b/include/winternl.h
index 8b895a9392..d5c8d76ccf 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -974,7 +974,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
 } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
 
 typedef enum _THREADINFOCLASS {
-    ThreadBasicInformation,
+    ThreadBasicInformation = 0,
     ThreadTimes,
     ThreadPriority,
     ThreadBasePriority,
@@ -1008,6 +1008,7 @@ typedef enum _THREADINFOCLASS {
     ThreadUmsInformation,
     ThreadCounterProfiling,
     ThreadIdealProcessorEx,
+    ThreadDescription = 38,
     MaxThreadInfoClass
 } THREADINFOCLASS;
 
@@ -1027,6 +1028,12 @@ typedef struct _THREAD_DESCRIPTOR_INFORMATION
     LDT_ENTRY   Entry;
 } THREAD_DESCRIPTOR_INFORMATION, *PTHREAD_DESCRIPTOR_INFORMATION;
 
+typedef struct _THREAD_DESCRIPTION_INFORMATION
+{
+    DWORD  Length;
+    WCHAR *Description;
+} THREAD_DESCRIPTION_INFORMATION, *PTHREAD_DESCRIPTION_INFORMATION;
+
 typedef struct _KERNEL_USER_TIMES {
     LARGE_INTEGER  CreateTime;
     LARGE_INTEGER  ExitTime;




More information about the wine-cvs mailing list