1.进程枚举
线程函数PhProcessProviderUpdate --> PhEnumProcesses-->PhEnumProcessesEx-->NtQuerySystemInformation 实现获取进程列表,返回PSYSTEM_PROCESS_INFORMATION 数组。
#define PROCESS_ID_BUCKETS 64
#define PROCESS_ID_TO_BUCKET_INDEX(ProcessId) ((HandleToUlong(ProcessId) / 4) & (PROCESS_ID_BUCKETS - 1))
最大值是64,&(PROCESS_ID_BUCKETS - 1) ,确保数组在0 ~ 63 之间。
static PSYSTEM_PROCESS_INFORMATION pidBuckets[PROCESS_ID_BUCKETS];用于保存当次进程信息,减少数组对比次数及内存。
bucketIndex = PROCESS_ID_TO_BUCKET_INDEX(process->UniqueProcessId);
process->UniqueProcessKey = (ULONG_PTR)pidBuckets[bucketIndex];
pidBuckets[bucketIndex] = process;
利用UniqueProcessKey 将同一个hash 的id 形成链表。
将进程通过PhpAddProcessItem添加到PhProcessHashSet 哈希表中。
PPH_HASH_ENTRY PhProcessHashSet[256] = PH_HASH_SET_INIT; //全局进程信息,用于对比每次进程的更新信息对比
每次更新进程列表时,PhProcessHashSet与pidBuckets 数组对比,先查找进程已退出进程列表。
通过进程的ProcessSequenceNameber 或者CreateTime 对比,二者不一致则表示有进程退出。
如果有进程退出,则发一个进程退出回调。
// Raise the process removed event.
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackProcessProviderRemovedEvent),
processItem);在将该退出进程添加到退出列表中。然后通过PhpRemoveProcessItem ,最终通过PhRemoveEntryHashSet来删除对应的退出进程列表。
如果pidBuckets 存在,PhProcessHashSet没有则表明是新创建进程。通过PhpAddProcessItem 添加到PhProcessHashSet 哈希表里。
进程哈希函数
进程对比函数
添加一个AddEvent , 触发一个添加回调 。
否则就是更新进程列表信息,最后都会有更新回调。
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackProcessProviderUpdatedEvent), NULL);
UI的添加、修改、删除回调。
添加、删除、修改都只是将processItem 添加到PhMwpProcessEventQueue 列表中。 更新回调则调用PhMwpOnProcessesUpdated, 从刚才的全局链表中PhMwpProcessEventQueue 找到对应的事件,来完成对应的添加、修改、删除。
以添加为例:
通过PhAddProcessNode 完成添加。根据PPH_PROCESS_ITEM 创建 PH_PROCESS_NODE 。
根据进程父子关系将根结点,添加到ProcessNodeRootList 里面。ProcessNodeList 是全量的ProcessNode 节点,并且保存到ProcessNodeHashSet(方便查询) 里面。最后通知UI 显示。
获取到PPH_TREENEW_NODE 后,随后添加到Context 的FlatList 。
Context 是保存在一个全局WindowContextHashTable 里。进程TreeNew创建的时候,会新建一个context ,并保存到WindowContextHashTable 里面。
PhTnpWndProc的WM_PAINT(PhTnpOnPaint),通过PhTnpGetCellText获取需要绘制的TEXT。
回调函数到PhpProcessTreeNewCallback。
从获取进程列表信息,到UI绘制,就全部链接起来了。