如何将通过NtQueryInformationThread获取线程名的C代码改写为C++实现
线程名查询函数C++实现方案
原实现核心逻辑为调用NtQueryInformationThread获取ThreadNameInformation信息,改写为C版本时可利用RAII特性优化内存管理,也可适配C标准字符串类型,以下是两种常用实现:
版本1:兼容原有PH_STRING类型接口
该版本保留和原C函数完全一致的调用方式,仅内部用C++特性优化内存安全,避免手动释放内存导致的泄漏风险:
#include <ntstatus.h> #include <windows.h> #include <memory> // 需引入ProcessHacker相关头文件获取PH_STRING、PhAllocate/PhFree等定义 NTSTATUS PhGetThreadName( _In_ HANDLE ThreadHandle, _Out_ PPH_STRING *ThreadName ) { NTSTATUS status; ULONG bufferSize = 0x100; ULONG returnLength = 0; // 智能指针自动管理分配的内存,即使函数中途退出也会自动释放 auto bufferDeleter = [](PTHREAD_NAME_INFORMATION ptr) { PhFree(ptr); }; std::unique_ptr<THREAD_NAME_INFORMATION, decltype(bufferDeleter)> buffer( static_cast<PTHREAD_NAME_INFORMATION>(PhAllocate(bufferSize)), bufferDeleter ); status = NtQueryInformationThread( ThreadHandle, ThreadNameInformation, buffer.get(), bufferSize, &returnLength ); if (status == STATUS_BUFFER_OVERFLOW) { // 重置缓冲区,分配符合长度要求的新内存 buffer.reset(); bufferSize = returnLength; buffer.reset(static_cast<PTHREAD_NAME_INFORMATION>(PhAllocate(bufferSize))); status = NtQueryInformationThread( ThreadHandle, ThreadNameInformation, buffer.get(), bufferSize, &returnLength ); } if (NT_SUCCESS(status)) { *ThreadName = PhCreateStringFromUnicodeString(&buffer->ThreadName); } return status; }
版本2:C++原生风格实现(返回标准字符串)
如果不需要依赖ProcessHacker的自定义字符串结构,可以直接返回C++标准std::wstring,调用更便捷,无需额外管理字符串内存:
#include <ntstatus.h> #include <windows.h> #include <memory> #include <string> // 函数返回调用状态,线程名通过输出参数std::wstring返回 NTSTATUS GetThreadName( _In_ HANDLE ThreadHandle, _Out_ std::wstring& threadName ) { NTSTATUS status; ULONG bufferSize = 0x100; ULONG returnLength = 0; // 用系统API分配内存,不依赖第三方库 auto bufferDeleter = [](PTHREAD_NAME_INFORMATION ptr) { VirtualFree(ptr, 0, MEM_RELEASE); }; std::unique_ptr<THREAD_NAME_INFORMATION, decltype(bufferDeleter)> buffer( static_cast<PTHREAD_NAME_INFORMATION>(VirtualAlloc(NULL, bufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)), bufferDeleter ); status = NtQueryInformationThread( ThreadHandle, ThreadNameInformation, buffer.get(), bufferSize, &returnLength ); if (status == STATUS_BUFFER_OVERFLOW) { buffer.reset(); bufferSize = returnLength; buffer.reset(static_cast<PTHREAD_NAME_INFORMATION>(VirtualAlloc(NULL, bufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))); status = NtQueryInformationThread( ThreadHandle, ThreadNameInformation, buffer.get(), bufferSize, &returnLength ); } if (NT_SUCCESS(status)) { threadName.assign(buffer->ThreadName.Buffer, buffer->ThreadName.Length / sizeof(WCHAR)); } else { threadName.clear(); } return status; }
注意事项
- 调用
NtQueryInformationThread需要进程持有对应线程的THREAD_QUERY_INFORMATION权限 THREAD_NAME_INFORMATION结构定义可从WDK头文件获取,也可根据官方规范自行声明- 若通过线程ID获取线程名,需要先调用
OpenThread拿到线程句柄再传入上述函数
内容的提问来源于stack exchange,提问作者Ahmed Mahmoud
相关产品推荐
相关产品推荐

