-
Нашел в сети несколько примеров, остановился на двух, оба они делают одно и то же (возвращают список процессов), но разными методами. Какой на ВАШ профессиональный взгляд метод, более правильно использовать? Код первого примера:
SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Result := (SnapProcHandle <> INVALID_HANDLE_VALUE);
if Result then
try
ProcEntry.dwSize := SizeOf(ProcEntry);
NextProc := Process32First(SnapProcHandle, ProcEntry);
while NextProc do
begin
FileName := ProcessFileNameByPID(ProcEntry.th32ProcessID, True);
if FileName = '' then FileName := ProcEntry.szExeFile;
Form1.ListBox1.Items.AddObject(FileName, Pointer(ProcEntry.th32ProcessID));
NextProc := Process32Next(SnapProcHandle, ProcEntry);
end;
finally
CloseHandle(SnapProcHandle);
end;
Код второго примера:
EnumProcesses(@PIDArray, SizeOf(PIDArray), cb);
ProcCount := cb div SizeOf(DWORD);
for I := 0 to ProcCount - 1 do
begin
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PIDArray[I]);
if not (hProcess=0) then
begin
EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb);
GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName));
Form1.ListBox1.Items.Add(ModuleName);
CloseHandle(hProcess);
end;
end;
И второй вопрос: как определить пользователя, под которым работает тот или иной процесс?
-
-
-
Спасибо, мужики, за реально лаконичные ответы :) насколько я увидел в обоих примерах используется код, аналогичный моему второму примеру. Просто интересно узнать, имеет ли право на жизнь первый мой пример, поскольку результатом его выполнения является список, аналогичный второму примеру, т.е. они оба работают.
Да, еще интересный момент: процессы с именем csrss.exe и winlogon.exe оба примера возвращают вот в таком загадочном виде (остальные нормально) \??\С:\Windows\System32\csrss.exe \??\С:\Windows\System32\winlogon.exe вот то, что выделил жирным, никто не знает что это за муть?
-
> они оба работают
2-й не будет работать под Win9x/Me
-
>>2-й не будет работать под Win9x/Me ну этих мамонтов я думаю уже не встречу в этой жизни, так что не критично. Просто интересно, там же список добывается совершенно иным способом (CreateToolhelp32Snapshot).
И по поводу артифактов \??\ ни у кого мыслей нет?
-
> И по поводу артифактов \??\
насколько я помню, это эквивалент \Device\Harddrive0
-
вернее даже \Device\Harddrive0\Partition1
-
> И по поводу артифактов \??\ ни у кого мыслей нет?
пишется артефакт
мысль есть - ?? это корень пространства имен DOS-устройств диспетчера объектов Windows
Легче стало ?
-
> вернее даже \Device\Harddrive0\Partition1
неа
-
> [0] WanderBuild (23.01.09 13:10)
> И второй вопрос: как определить пользователя, под которым > работает тот или иной процесс?
способов получения списка процессов еще, как минимум 2, это доступных из user-mode, возможно и еще есть. в вашем случае полезнее способ с использованием WTSEnumerateProcesses.
-
> Игорь Шевченко © (23.01.09 17:12)
ну хоть первое слово угадал - Device -)
-
> способов получения списка процессов еще, как минимум 2, > это доступных из user-mode
ага, еще через WMI можно
-
Всем спасибо за быстрый отклик и ответы, считаю вопрос исчерпанным.
Специально для Игорь Шевченко: Тем не менее тоже спасибо, хоть и слышу в вашем ответе нескрытое презрение. Простите, что обидел Вас неправильным написанием слова, если вам станет от этого хоть чуточку легче, то оговорюсь, что ошибку заметил сразу после того как запостил сообщение, но изменить его я уже не мог.
-
Имена, начинающиеся с \??\ (или с \Device\..) называются ядерными именами, потому как внутре ядро работает именно с такими именами и ни с какими другими.
Тем не менее, почему именно у этих двух процессов такие имена исполняемых файлов - потому что первый (csrss.exe) запускается процессом smss.exe, а второй (winlogon.exe) запускается процессом csrss.exe. Отличительная особенность этих процессов состоит в том, что они не используют подсистему Win32 для запуска процессов - в случае smss.exe ее еще не существует, а в случае csrss.exe - он мало того, что ее инициализирует, так еще является и серверной ее частью (в частности, отрабатывает CreateProcess).
Поэтому в этих процессах используются только вызовы функций Native API, которые отличаются тем, что не понимают в качестве имен файлов строки, начинающиеся на C:\, D:\ и так далее. Зато они понимают имена, которые содержатся в пространстве имен диспетчера объектов Windows (он к тому времени уже проинициализирован, ядерные имена для пути к разделам диска прописаны, драйверы для дисков установлены, в общем, есть все данные, чтобы по ядерному имени добраться до файла).
Собственно, такое имя можно получить и из привычного имени файла, вызвав RtlPathNameToNtPathName, и, соответственно, наоборот, из ядерного имени файла можно получить (не всегда) привычное.
-
>>Игорь Шевченко - а теперь огромное спасибо за крайне интересную и весьма редкую информацию. И ещё раз извините.
-
Удалено модератором
-
> WanderBuild (23.01.09 13:10) > > И второй вопрос: как определить пользователя, под которым > работает тот или иной процесс?
type
TWinStationGetProcessSid = function(hServer: Cardinal;
ProcessId: Cardinal;
ProcessStartTime: _FILETIME;
pProcessUserSid: PByte;
var dwSidSize: Cardinal): Boolean; stdcall;
var
_WinStationGetProcessSid: TWinStationGetProcessSid;
function _GetOSVersion: Cardinal;
var
OSVersionInfo: TOSVersionInfo;
begin
Result:= 0;
FillChar(OSVersionInfo, Sizeof(OSVersionInfo), 0);
OSVersionInfo.dwOSVersionInfoSize:= SizeOf(OSVersionInfo);
if GetVersionEx(OSVersionInfo) then
begin
if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
begin
if OSVersionInfo.dwMajorVersion = 5 then
begin
if OSVersionInfo.dwMinorVersion = 0 then
Result:= 50
else if OSVersionInfo.dwMinorVersion = 2 then
Result:= 52
else if OSVersionInfo.dwMinorVersion = 1 then
Result:= 51
end;
if OSVersionInfo.dwMajorVersion = 6 then
begin
if OSVersionInfo.dwMinorVersion = 0 then
Result:= 60
else if OSVersionInfo.dwMinorVersion = 1 then
Result:= 61;
end;
end;
end;
end;
function _EnablePrivilege(Privilege: string): Boolean;
var
TokenHandle: THandle;
TokenPrivileges: TTokenPrivileges;
ReturnLength: Cardinal;
begin
Result:= False;
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then
begin
LookupPrivilegeValue(nil, PChar(Privilege), TokenPrivileges.Privileges[0].Luid);
TokenPrivileges.PrivilegeCount:= 1;
TokenPrivileges.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
if AdjustTokenPrivileges(TokenHandle, False, TokenPrivileges, 0, nil, ReturnLength) then
Result:= True;
end;
end;
function _GetProcessUserAndDomainName_1(PID: DWORD; var UserName: string; var DomainName: string): Boolean;
type
TOKEN_USER = record
User: TSidAndAttributes;
end;
PTOKEN_USER = ^TOKEN_USER;
TTOKEN_USER = TOKEN_USER;
var
hToken: THandle;
cbBuf: Cardinal;
ptiUser: PTOKEN_USER;
snu: SID_NAME_USE;
Domain, User: array[0..1024] of Char;
chUser: DWORD;
chDomain: DWORD;
hProcess: THandle;
begin
Result:= False;
UserName:= '';
DomainName:= '';
chDomain:= 1024;
chUser:= 1024;
hProcess:= OpenProcess(MAXIMUM_ALLOWED, False, PID);
if hProcess <> 0 then
begin
if OpenProcessToken(hProcess, MAXIMUM_ALLOWED, hToken) then
begin
try
GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);
GetMem(ptiUser, cbBuf);
if GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf) then
begin
if LookupAccountSid(nil, ptiUser.User.Sid, User, chUser, Domain, chDomain, snu) then
begin
UserName:= User;
DomainName:= Domain;
end;
end;
FreeMem(ptiUser);
finally
CloseHandle(hToken);
end;
end;
end;
end;
function _GetProcessUserAndDomainName_2(PID: DWORD; var UserName: string; var DomainName: string): Boolean;
var
hProcess: THandle;
lpCreationTime, lpExitTime, lpKernelTime, lpUserTime: _FILETIME;
pProcessUserSid: Pointer;
User, Domain: PChar;
cbUser, cbDomain: Cardinal;
dwSidSize: Cardinal;
CreateTime: TSystemTime;
begin
Result:= False;
UserName:= '';
DomainName:= '';
if _GetOSVersion >= 60 then
hProcess:= OpenProcess($1000, False, PID)
else
hProcess:= OpenProcess(MAXIMUM_ALLOWED, False, PID);
if hProcess <> 0 then
begin
try
dwSidSize:= 0;
GetProcessTimes(hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
FileTimeToSystemTime(lpCreationTime, CreateTime);
_WinStationGetProcessSid(0, PID, lpCreationTime, nil, dwSidSize);
GetMem(pProcessUserSid, dwSidSize);
if _WinStationGetProcessSid(0, PID, lpCreationTime, pProcessUserSid, dwSidSize) then
begin
cbUser:= 0;
cbDomain:= 0;
LookupAccountSid(nil, pProcessUserSid, nil, cbUser, nil, cbDomain, dwSidSize);
GetMem(User, cbUser);
GetMem(Domain, cbDomain);
Result:= LookupAccountSid(nil, pProcessUserSid, User, cbUser, Domain, cbDomain, dwSidSize);
SetLength(UserName, cbUser);
SetLength(DomainName, cbDomain);
lstrcpy(PChar(UserName), User);
lstrcpy(PChar(DomainName), Domain);
FreeMem(User);
FreeMem(Domain);
end;
FreeMem(pProcessUserSid);
finally
CloseHandle(hProcess);
end;
end;
end;
function _GetProcessUserAndDomainName(PID: DWORD; var UserName: string; var DomainName: string): Boolean;
begin
if _GetOSVersion > 50 then
Result:= _GetProcessUserAndDomainName_2(PID, UserName, DomainName)
else
Result:= _GetProcessUserAndDomainName_1(PID, UserName, DomainName); end;
procedure TForm1.FormCreate(Sender: TObject);
begin
_EnablePrivilege('SeDebugPrivilege');
if _GetOSVersion > 50 then
@_WinStationGetProcessSid:= GetProcAddress(LoadLibrary('winsta.dll'), 'WinStationGetProcessSid');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
User, Domain: String;
begin
_GetProcessUserAndDomainName(1156, User, Domain);
ShowMessage(Domain + '\' + User);
end;
-
-
> SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, > 0);
Работает в WOW64, показывает как 64-битные процессы, так и 32-битные.
Второй в WOW64 показывает только 32-х битные.
|