[PATCH 1/3] kernel32/tests: Add some tests for thread description API.
Nikolay Sivov
nsivov at codeweavers.com
Sun Nov 24 11:34:20 CST 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
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;
--
2.24.0
More information about the wine-devel
mailing list