按照惯例,先来看一下EnumProcesses的底层实现到底是个什么东东??其实其内部还是调用了Nt系列的函数,通过宏传递参数,查询各种信息。最终返出各个进程的ID值
BOOL
WINAPI
EnumProcesses(DWORD *lpidProcess,
DWORD cb,
LPDWORD lpcbNeeded)
{
NTSTATUS Status;
DWORD Size = MAXSHORT, Count;
PSYSTEM_PROCESS_INFORMATION ProcInfo;//先定义两个结构体用来承接NtQuerySystemInformation系列的返回值
PSYSTEM_PROCESS_INFORMATION ProcInfoArray;
do
{
//申请内存
ProcInfoArray = LocalAlloc(LMEM_FIXED, Size);
if (ProcInfoArray == NULL)
{
return FALSE;
}
//查询进程信息
Status = NtQuerySystemInformation(SystemProcessInformation, ProcInfoArray, Size, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
//如果内存长度不够,释放,继续申请
LocalFree(ProcInfoArray);
Size += MAXSHORT;
continue;
}
//查询结束
break;
}
while (TRUE);
if (!NT_SUCCESS(Status))
{
//若Status返回值失败,则设置错误码,结束函数
LocalFree(ProcInfoArray);
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
Count = 0;
ProcInfo = ProcInfoArray;
_SEH2_TRY
{
do
{
if (Count < cb / sizeof(DWORD))
{
//保存id值
lpidProcess[Count] = (DWORD)ProcInfo->UniqueProcessId;
Count++;
}
if (ProcInfo->NextEntryOffset == 0)
{
//如果进程链表结束,则退出
break;
}
//遍历所有进程
ProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcInfo + ProcInfo->NextEntryOffset);
}
while (TRUE);
*lpcbNeeded = Count * sizeof(DWORD);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
LocalFree(ProcInfoArray);
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
//释放内存,返回成功
LocalFree(ProcInfoArray);
return TRUE;
}
EnumProcess使用举例:
通过进程ImageName得到进程ID
ULONG GetActiveProcessIdW(wchar_t* ImageName)
{
int i;
wchar_t* TranslatedProcessName;
DWORD ProcessId[1024] = {};
wchar_t ProcessFullPath[1024] = {};
DWORD IsNeeded = NULL;
HANDLE ProcessHandle;
wchar_t* NameOnly = 0;//只有进程名,没有完整路径
if (EnumProcesses(ProcessId, sizeof(ProcessId), &IsNeeded))
{
for (i = 0; i < (int)(IsNeeded / sizeof(DWORD)); i++)
{
if (ProcessId[i] != NULL)
{
//提升权限,打开进程
ProcessHandle = KtOpenProcess(PROCESS_QUERY_INFORMATION,
false,
ProcessId[i]);
if (ProcessHandle != NULL)
{
if (GetProcessImageFileNameW(ProcessHandle,
ProcessFullPath,
_countof(ProcessFullPath)) > NULL)
{
TranslatedProcessName = (wchar_t*)TranslateNativeNameW(ProcessFullPath);
lstrcpyW(ProcessFullPath, TranslatedProcessName);
VirtualFree((void*)TranslatedProcessName, NULL, MEM_RELEASE);
KtCloseHandle(ProcessHandle);
if (_wcsicmp(ProcessFullPath, ImageName) == 0)
{
//如果不匹配,说明传的参数不是完整路径
return ProcessId[i];
}
else
{
//寻找最后一个'\'的位置
NameOnly = wcsrchr(ProcessFullPath, L'\\');
if (NameOnly)
{
//越过'\'
NameOnly++;
if (_wcsicmp(NameOnly, ImageName) == 0)
{
return ProcessId[i];
}
}
}
}
else
{
KtCloseHandle(ProcessHandle);
}
}
}
}
}
return NULL;
}
越过山丘,会看见美景依旧!
参考资料:
Reactos