mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 00:40:26 +08:00
[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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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) ));
|
||||
}
|
||||
93
dll/win32/kernel32/kernel32_vista/ThreadDescription.c
Normal file
93
dll/win32/kernel32/kernel32_vista/ThreadDescription.c
Normal 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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user