@@ -1724,6 +1724,140 @@ extern "C" {
17241724 ULONG_PTR pTemp = 0 ;
17251725 };
17261726
1727+
1728+ #if _MSC_VER >= 1200
1729+ #pragma warning(push)
1730+ #pragma warning(disable:4355) // "this": 用于基成员初始值设定项列表
1731+ #endif
1732+
1733+ /*
1734+ 进程列表遍历迭代器
1735+ Iterator for enumerate the process list
1736+
1737+ 用法 Usage
1738+ for (auto pSPI : CM2EnumProcess(status)) { }
1739+
1740+ status 是初始化遍历返回值(可选)
1741+ status is the return value for initialization (Optional)
1742+ */
1743+ class CM2EnumProcess
1744+ {
1745+ public:
1746+ class CM2EnumProcessIterator
1747+ {
1748+ private:
1749+ CM2EnumProcess* m_EnumProcess;
1750+
1751+ public:
1752+ FORCEINLINE CM2EnumProcessIterator (
1753+ _In_ CM2EnumProcess* FindFile) :
1754+ m_EnumProcess(FindFile)
1755+ {
1756+
1757+ }
1758+
1759+ FORCEINLINE ~CM2EnumProcessIterator ()
1760+ {
1761+
1762+ }
1763+
1764+ FORCEINLINE void operator ++()
1765+ {
1766+ // 如果pSPI和下个结构偏移都存在,则继续循环,否则清零
1767+ if (m_EnumProcess->pSPI && m_EnumProcess->pSPI ->NextEntryOffset )
1768+ {
1769+ ULONG_PTR NextSPI = reinterpret_cast <ULONG_PTR>(m_EnumProcess->pSPI );
1770+ NextSPI += m_EnumProcess->pSPI ->NextEntryOffset ;
1771+ m_EnumProcess->pSPI = reinterpret_cast <PSYSTEM_PROCESS_INFORMATION>(NextSPI);
1772+ }
1773+ else
1774+ {
1775+ m_EnumProcess->pSPI = nullptr ;
1776+ }
1777+ }
1778+
1779+ // 根据迭代器循环特性,使用不等于操作符遍历目录
1780+ FORCEINLINE bool operator !=(const CM2EnumProcessIterator& Item)
1781+ {
1782+ UNREFERENCED_PARAMETER (Item);
1783+ return (m_EnumProcess->pSPI != nullptr );
1784+ }
1785+
1786+ FORCEINLINE PSYSTEM_PROCESS_INFORMATION operator *()
1787+ {
1788+ return m_EnumProcess->pSPI ;
1789+ }
1790+ };
1791+
1792+ private:
1793+ CM2EnumProcessIterator Iterator;
1794+ PVOID lpBuffer;
1795+ PSYSTEM_PROCESS_INFORMATION pSPI;
1796+
1797+ public:
1798+ // 初始化文件遍历, 不内联考虑到大量使用本迭代器时实现函数复用以节约空间
1799+ DECLSPEC_NOINLINE CM2EnumProcess (
1800+ _Out_ NTSTATUS* InitStatus = nullptr ) :
1801+ Iterator(this ),
1802+ lpBuffer(nullptr ),
1803+ pSPI(nullptr )
1804+
1805+ {
1806+ NTSTATUS status = STATUS_SUCCESS;
1807+ DWORD dwLength = 0 ;
1808+
1809+ do
1810+ {
1811+ // 获取进程信息大小
1812+ status = NtQuerySystemInformation (
1813+ SystemProcessInformation,
1814+ nullptr ,
1815+ 0 ,
1816+ &dwLength);
1817+ if (status != STATUS_INFO_LENGTH_MISMATCH) break ;
1818+
1819+ // 为令牌信息分配内存,如果失败则返回
1820+ status = M2HeapAlloc (
1821+ dwLength,
1822+ lpBuffer);
1823+ if (!NT_SUCCESS (status)) break ;
1824+
1825+ // 获取进程信息
1826+ status = NtQuerySystemInformation (
1827+ SystemProcessInformation,
1828+ lpBuffer,
1829+ dwLength,
1830+ &dwLength);
1831+ if (!NT_SUCCESS (status)) break ;
1832+
1833+ // 设置遍历开始地址
1834+ pSPI = reinterpret_cast <PSYSTEM_PROCESS_INFORMATION>(lpBuffer);
1835+
1836+ } while (false );
1837+
1838+ if (InitStatus) *InitStatus = status;
1839+ }
1840+
1841+ FORCEINLINE ~CM2EnumProcess ()
1842+ {
1843+ if (lpBuffer) M2HeapFree (lpBuffer);
1844+ }
1845+
1846+ FORCEINLINE CM2EnumProcessIterator& begin ()
1847+ {
1848+ return Iterator;
1849+ }
1850+
1851+ FORCEINLINE CM2EnumProcessIterator& end ()
1852+ {
1853+ return Iterator;
1854+ }
1855+ };
1856+
1857+ #if _MSC_VER >= 1200
1858+ #pragma warning(pop)
1859+ #endif
1860+
17271861 /*
17281862 SuGetSystemTokenCopy函数获取一个当前会话SYSTEM用户令牌的副本。
17291863 The SuGetSystemTokenCopy function obtains a copy of current session SYSTEM
@@ -1739,21 +1873,16 @@ extern "C" {
17391873 NTSTATUS status = STATUS_SUCCESS;
17401874 DWORD dwWinLogonPID = (DWORD)-1 ;
17411875 DWORD dwSessionID = (DWORD)-1 ;
1742- PSYSTEM_PROCESS_INFORMATION pSPI = nullptr ;
17431876 HANDLE hProcessToken = nullptr ;
17441877
17451878 do
17461879 {
1747- // 初始化进程遍历
1748- CSuProcessSnapshot Snapshot (&status);
1749- if (!NT_SUCCESS (status)) break ;
1750-
17511880 // 获取当前进程令牌会话ID
17521881 status = SuGetCurrentProcessSessionID (&dwSessionID);
17531882 if (!NT_SUCCESS (status)) break ;
17541883
17551884 // 遍历进程寻找winlogon进程并获取PID
1756- while (Snapshot. Next (&pSPI ))
1885+ for ( auto pSPI : CM2EnumProcess (&status ))
17571886 {
17581887 if (pSPI->SessionId != dwSessionID) continue ;
17591888 if (pSPI->ImageName .Buffer == nullptr ) continue ;
@@ -1765,6 +1894,9 @@ extern "C" {
17651894 }
17661895 }
17671896
1897+ // 如果初始化进程遍历失败,则返回错误
1898+ if (!NT_SUCCESS (status)) break ;
1899+
17681900 // 如果没找到进程,则返回错误
17691901 if (dwWinLogonPID == -1 )
17701902 {
0 commit comments