Files
reactos/dll/win32/kernel32/kernel32_vista/ThreadDescription.c
T
Hermès Bélusca-Maïto dfaac47afc [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.
2026-03-29 19:35:41 +02:00

94 lines
3.1 KiB
C

/*
* 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 <[email protected]>
*/
#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);
}