[KERNEL32_VISTA] Reimplement [Get|Set]ThreadDescription() (#8484)

- `GetThreadDescription()`: since there may be concurrent `SetThreadDescription()`
  invocations being executed, we need to loop over the buffer allocation size until
  we can successfully capture the thread name.
  Also, we can directly re-use the temporary buffer, after resizing, for
  the output description buffer.

- `SetThreadDescription()`: Use `RtlInitUnicodeStringEx()` instead of reimplementing
  its internal logic.
This commit is contained in:
Hermès Bélusca-Maïto
2025-11-23 22:18:39 +01:00
parent a4621bb280
commit dfaac47afc
4 changed files with 96 additions and 30 deletions

View File

@@ -7,8 +7,8 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys ..)
spec2def(kernel32_vista.dll kernel32_vista.spec ADD_IMPORTLIB)
list(APPEND SOURCE
firmware.c
EnumSystemLocalesEx.c
firmware.c
GetLocaleInfoEx.c
GetFileInformationByHandleEx.c
GetFinalPathNameByHandle.c
@@ -19,8 +19,8 @@ list(APPEND SOURCE
IsValidLocaleName.c
LCIDToLocaleName.c
LocaleNameToLCID.c
SetThreadDescription.c
sync.c
ThreadDescription.c
threadpool.c
vista.c)

View File

@@ -1,28 +0,0 @@
#include "k32_vista.h"
#define NDEBUG
#include <debug.h>
#undef TRACE
#define TRACE DPRINT
/***********************************************************************
* SetThreadDescription (kernelbase.@)
*/
HRESULT WINAPI DECLSPEC_HOTPATCH SetThreadDescription( HANDLE thread, PCWSTR description )
{
THREAD_NAME_INFORMATION info;
int length;
TRACE( "(%p, %s)\n", thread, debugstr_w( description ));
length = description ? lstrlenW( description ) * sizeof(WCHAR) : 0;
if (length > USHRT_MAX)
return HRESULT_FROM_NT(STATUS_INVALID_PARAMETER);
info.ThreadName.Length = info.ThreadName.MaximumLength = length;
info.ThreadName.Buffer = (WCHAR *)description;
return HRESULT_FROM_NT(NtSetInformationThread( thread, ThreadNameInformation, &info, sizeof(info) ));
}

View File

@@ -0,0 +1,93 @@
/*
* PROJECT: ReactOS Win32 Base API
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: NT10+ Thread Description helpers
* COPYRIGHT: Copyright 2025-2026 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
#include "k32_vista.h"
HRESULT
WINAPI
DECLSPEC_HOTPATCH
GetThreadDescription(
_In_ HANDLE hThread,
_Outptr_result_z_ PWSTR* ppszThreadDescription)
{
PTHREAD_NAME_INFORMATION NameInfo = NULL;
PVOID ptr;
NTSTATUS Status;
ULONG Length;
*ppszThreadDescription = NULL;
/* Since there may be concurrent SetThreadDescription() invocations being
* executed, we need to loop over the buffer allocation size until we can
* successfully capture the thread name. */
Length = 0;
Status = NtQueryInformationThread(hThread, ThreadNameInformation, NULL, 0, &Length);
if (Status != STATUS_BUFFER_TOO_SMALL)
return HRESULT_FROM_NT(Status);
/* Loop again only if we get buffer-too-small types of errors;
* otherwise, break the loop: any error will be handled below. */
while (Status == STATUS_INFO_LENGTH_MISMATCH ||
Status == STATUS_BUFFER_TOO_SMALL)
{
/* (Re-)allocate the information buffer */
ptr = (NameInfo ? LocalReAlloc(NameInfo, Length, LMEM_MOVEABLE)
: LocalAlloc(LMEM_FIXED, Length));
if (!ptr)
{
Status = STATUS_NO_MEMORY;
break;
}
NameInfo = ptr;
Status = NtQueryInformationThread(hThread, ThreadNameInformation,
NameInfo, Length, &Length);
}
if (!NT_SUCCESS(Status))
{
LocalFree(NameInfo);
return HRESULT_FROM_NT(Status);
}
/*
* We already have a suitable memory buffer, containing a UNICODE_STRING
* followed by the actual string data. Just move the string back to the
* beginning of the buffer and resize it down. Since sizeof(UNICODE_STRING)
* is larger than sizeof(WCHAR), we also have space for the NUL-terminator.
*/
*ppszThreadDescription = (PWSTR)NameInfo;
Length = NameInfo->ThreadName.Length;
if (Length)
RtlMoveMemory(*ppszThreadDescription, NameInfo->ThreadName.Buffer, Length);
(*ppszThreadDescription)[Length / sizeof(WCHAR)] = UNICODE_NULL;
/* Resize down the buffer. If the call fails, the old buffer
* is still valid, but is larger than what is necessary. */
ptr = LocalReAlloc(*ppszThreadDescription, Length + sizeof(WCHAR), LMEM_FIXED);
if (ptr)
*ppszThreadDescription = ptr;
return HRESULT_FROM_NT(Status);
}
HRESULT
WINAPI
DECLSPEC_HOTPATCH
SetThreadDescription(
_In_ HANDLE hThread,
_In_ PCWSTR lpThreadDescription)
{
THREAD_NAME_INFORMATION NameInfo;
NTSTATUS Status;
Status = RtlInitUnicodeStringEx(&NameInfo.ThreadName, lpThreadDescription);
if (NT_SUCCESS(Status))
{
Status = NtSetInformationThread(hThread, ThreadNameInformation,
&NameInfo, sizeof(NameInfo));
}
return HRESULT_FROM_NT(Status);
}

View File

@@ -59,6 +59,7 @@
@ stdcall CompareStringOrdinal(ptr long ptr long long)
@ stdcall GetNamedPipeClientProcessId(ptr ptr)
@ stdcall GetThreadDescription(ptr ptr) # Win 10
@ stdcall SetThreadDescription(ptr wstr) # Win 10
@ stdcall GetSystemTimePreciseAsFileTime(ptr) kernel32.GetSystemTimeAsFileTime
@ stdcall TrySubmitThreadpoolCallback(ptr ptr ptr)