_SYSTEM_PROCESS_INFORMATION结构向后兼容性
_SYSTEM_PROCESS_INFORMATION struct backward compatibility
Goal
编写一个函数来查询进程的线程状态。
溶液
使用这篇有用的帖子:迭代流程的独特技术并制定初始函数:
bool IterateOverThreads() {
NTSTATUS status;
PSYSTEM_PROCESS_INFORMATION spi;
ULONG lBufferSize = 0;
status = ::NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS::SystemProcessInformation, 0, 0, & lBufferSize);
if (0xC0000004L != status || 0 == lBufferSize)
return false;
unique_ptr<byte[]> pMemory(new byte[lBufferSize]);
spi = (PSYSTEM_PROCESS_INFORMATION)pMemory.get();
// get System Information
if (!NT_SUCCESS(status = ::NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS::SystemProcessInformation, spi, lBufferSize, & lBufferSize)))
return false;
// Loop over the list until we reach the last entry
while (spi->NextEntryDelta) {
// Calculate the address of the next entry.
spi = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)spi + spi->NextEntryDelta);
// iterate over threads
for (size_t ii = 0; ii < spi->ThreadCount; ++ii) {
// do whatever with thread attributes
spi->Threads[ii].State;
spi->Threads[ii].WaitReason;
}
}
return true;
}
问题1
我的解决方案/项目必须使用 Microsoft SDK 版本 7.1。
SDK 版本之间的结构SYSTEM_PROCESS_INFORMATION
已按以下方式更改:
Microsoft SDKsWindowsv7.1AIncludewinternl.h
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
BYTE Reserved1[52];
PVOID Reserved2[3];
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
记录在 NtQuerySystemInformation 中
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
BYTE Reserved1[48];
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
PVOID Reserved2;
ULONG HandleCount;
ULONG SessionId;
PVOID Reserved3;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG Reserved4;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
PVOID Reserved5;
SIZE_T QuotaPagedPoolUsage;
PVOID Reserved6;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION;
因此,我不能"享受"使用NumberOfThreads
(或其他人)之类的成员。
修复问题 1:
根据文档在我的代码中定义SYSTEM_PROCESS_INFORMATION
自己
问题2
我的应用程序在所有大于等于XP的Windows上运行。
问题
我的代码安全吗? 意思是,访问spi->ThreadCount
安全吗? 我可以假设那里的字节是有效的吗? 在较旧的 Windows 版本上从我自己定义的结构中读取字节是否有风险?
(我认为)SYSTEM_PROCESS_INFORMATION
定义之一
现在它对所有当前的Windows版本(包括XP)都有效。
访问 spi->线程计数安全?
是的,安全。 所有当前构建的最小值。(说XP已经不会改变)。这在未来的构建中是否安全(结构未更改)已经是另一个问题。
我的代码安全吗?
不,错了。 2分的最小值。 首先,在您第一次调用NtQuerySystemInformation
时获得lBufferSize
之后,在第二次调用中使用它之前 - 所需的大小可以更改(增长) - 所以真的需要对NtQuerySystemInformation
进行单次调用,但在循环中直到你得到STATUS_INFO_LENGTH_MISMATCH
。 您的代码可以工作,但有时会失败。
// Loop over the list until we reach the last entry while (spi->NextEntryDelta) {
这始终是错误 - 您丢失了最后一个条目,该条目具有NextEntryDelta == 0
布尔值不是函数的最佳主意,最好返回NTSTATUS
。
最小正确代码可能如下所示
NTSTATUS IterateOverThreads()
{
NTSTATUS status;
PVOID buf;
ULONG cb = 0x1000;
do
{
if (buf = LocalAlloc(0, cb))
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION spi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
DbgPrint("%wZn", &spi->ImageName);
if (ULONG NumberOfThreads = spi->NumberOfThreads)
{
PSYSTEM_THREAD_INFORMATION TH = spi->Threads;
do
{
DbgPrint("t%p %x %xn", TH->ClientId.UniqueThread, TH->ThreadState, TH->WaitReason);
} while (TH++, --NumberOfThreads);
}
} while (NextEntryOffset = spi->NextEntryOffset);
}
LocalFree(buf);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 提升序列化 1:73 的向后兼容性问题
- 在gcc中意外调用了Const重载.编译器错误或兼容性修复程序
- 各种版本的 Mac OSX 向后兼容性如何?(Xcode C++
- Visual Studio 19-17 库兼容性根据 GL 标志
- C++ ABI 兼容性问题/张量流
- Oracle OCCI 和 g++ 7.1 的兼容性问题
- 为什么库API+编译器ABI足以确保具有不同版本gcc的对象之间的兼容性
- 对指针和恒常性兼容性的引用
- 检查操作系统兼容性
- 添加noexcept是否会破坏二进制兼容性
- 右值需要分配什么向后兼容性
- 如何在不添加对库的依赖的情况下添加与库结构的兼容性
- 在Qt中使用C++Lambda函数作为插槽是否有助于保持库的二进制兼容性?
- python 和 swig 版本兼容性问题
- Tensorflow C++ API 和 Caffe 兼容性问题与 Glog 相关
- QT "relocation error" / "no version information available"运行时错误
- 当要求兼容性时,核心OpenGL上下文?
- 启用和禁用 RTTI 的模块之间的兼容性
- 值为 std::string,同时保持向后兼容性