Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос о процессах и не только... [D6, WinXP]


Alexis ©   (2004-04-10 19:21:00) 

При получении списка процессов(и полных путей к исполняемым файлам) в WinXP при помощи TLHelp32 и psAPI сталкиваюсь с такой проблемой : к некоторым процессам возвращаются такие пути :

?\SystemRoot\System32\smss.exe
\SystemRoot\System32\файл.exe
\??\D:\Windows\System32\winlogon.exe

К остальным процессам пути нормальные.Как из приведенного выше получить нормальные пути.
Подобное затрагивалось
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1080837801&n=5
но может есть еще варианты ?

И второй вопрос : как точно определить что процесс системный ?(со 100%-ной точностью)
Насколько знаю PID 0, 4 означают системный процесс, но многие другие процессы (например winlogon.exe, smss.exe) работают с другим PID-ом.
Process Explorer(на SysInternals.com) как-то определяет, кто разработчик программы (к процессам из директории Windows прописывает Microsoft Corporation.)
С помощью каких ф-ций это узнается? Нужны ли Debug привилегии?


Игорь Шевченко   (2004-04-19 15:46:00) [1]

Небольшое исправление:

   try
     Win32Check(GetTokenInformation(AccessToken, TokenUser, Info, 4096,
       ReturnLength));
     UserName := SidToName(Info^.Sid);
   finally
     FreeMem(Info);
     CloseHandle(AccessToken);
   end;


Недостающие unit'ы можно взять с
http://www.schevchenko.net.ru/SRC/Common_60.zip
и
http://www.schevchenko.net.ru/SRC/QuerySystemInformation_60.zip


Игорь Шевченко   (2004-04-19 15:37:00) [2]

Небольшой пример:
unit main;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 NtProcessInfo, ComCtrls;

type
 TfMain = class(TForm)
   ListView: TListView;
   procedure FormCreate(Sender: TObject);
 private
   FProcessList: THSNtProcessInfoList;

   procedure RefreshProcessList;
   procedure LookupProcessOwner(AProcess: THSNtProcessInfo);
   procedure DisplayProcess(AProcess: THSNtProcessInfo;
     const UserName: string);
 end;

var
 fMain: TfMain;

implementation
uses
 NtDll, HsNtDef, HsWinUtils;

{$R *.DFM}

type
 ZString = array[0..1024] of char;

function SIDToName (const SID: PSID): string;
var
 Use : SID_NAME_USE;
 DomainName : ZString;
 DomainNameLength : DWORD;
 Name : ZString;
 NameLength : DWORD;
begin
 if not LookupAccountSid(nil, SID, Name, NameLength, DomainName,
    DomainNameLength, Use) then
   Result := '***'
 else
   Result := Name;
end;

procedure TfMain.RefreshProcessList;
var
 Processes : Pointer;
 rc : NTSTATUS;
 Dummy: ULONG;
 I: Integer;
begin
 FProcessList.Free;
 Processes := QueryListInformation(SystemProcessesAndThreadsInformation, rc,
   Dummy);
 if NT_SUCCESS(rc) then begin
   FProcessList := THSNtProcessInfoList.Create(Processes);
   for I:=0 to Pred(FProcessList.Count) do
     if FProcessList[I].Info.ProcessId <> 0 then
       LookupProcessOwner(FProcessList[I]);
 end;

end;

procedure TfMain.FormCreate(Sender: TObject);
begin
 if not HSEnablePrivilege(SE_DEBUG_NAME) then
   raise Exception.CreateFmt('Can''t set debug privilege due to %s',
     [SysErrorMessage(GetLastError)]);
 RefreshProcessList;
end;

procedure TfMain.LookupProcessOwner(AProcess: THSNtProcessInfo);
var
 AccessToken : THandle;
 Info : PSIDANDATTRIBUTES;
 ReturnLength : DWORD;
 ProcessHandle: THandle;
 UserName: string;
begin
 ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, false,
    AProcess.Info.ProcessId);
 if ProcessHandle = 0 then
   Exit;
 try
   if not OpenProcessToken(ProcessHandle, TOKEN_QUERY, AccessToken) then
     Exit;
   GetMem (Info, 4096);
   try
     Win32Check(GetTokenInformation(AccessToken, TokenUser, Info, 1024,
       ReturnLength));
     UserName := SidToName(Info^.Sid);
   finally
     FreeMem(Info);
   end;
 finally
   CloseHandle(ProcessHandle);
 end;
 DisplayProcess(AProcess, UserName);
end;

procedure TfMain.DisplayProcess(AProcess: THSNtProcessInfo;
 const UserName: string);
begin
 with ListView.Items.Add do begin
   Caption := AProcess.ProcessName;
   SubItems.Add(UserName);
 end;
end;

end.


Игорь Шевченко   (2004-04-19 15:35:00) [3]


> как точно определить что процесс системный ?(


OpenProcess + OpenProcessToken + GetTokenInformation


Alexis   (2004-04-19 14:12:00) [4]

2 Игорь Шевченко-ведь я спрашиваю не о том, как открыть все процессы, а то как определить системность процесса.
Т.е. как определить системность процесса, к которому удалось получить Handle ?

(см. оригинальный вопрос)


Игорь Шевченко   (2004-04-19 12:28:00) [5]


> a tolko k tem, k kotorym udalos polucit Handle.


Для того, чтобы можно было открыть другие процессы, необходимо разрешить привилегию SeDebugName


Alexis   (2004-04-19 11:59:00) [6]

Eto jasno, cto ne ko vsem, a tolko k tem, k kotorym udalos polucit Handle.
No mne na vopros kto nibud mozet otvetit ili nikto ne znaet?


Игорь Шевченко   (2004-04-19 11:13:00) [7]


> но ко всем процессам возвращается имя залогиневшегося на
> данный момент пользователя.


Не ко всем...


Alexis   (2004-04-18 11:49:00) [8]

2 Игорь Шевченко - спасибо, это работает, но ко всем процессам возвращается имя залогиневшегося на данный момент пользователя.
Я попробовал изменить
GetTokenInformation(AccessToken, TokenUser, Info, 1024, ResultLength)
на
GetTokenInformation(AccessToken, TokenOwner, Info, 1024, ResultLength)
но это к нужному мне результату не привело.
Есть ли какой-то предопределенный макрос типа OWNER_SYSTEM?
Как же все таки определить кому принадлежит процесс?
С какими параметрами вызывать GetTokenInformation?


AndersoNRules   (2004-04-14 16:13:00) [9]

Otkuda vi vseo ato znayete?


Игорь Шевченко   (2004-04-13 14:46:00) [10]

type
 ZString = array[0..1024] of char;

function SIDToName (const SID: PSID): string;
var
 Use : SID_NAME_USE;
 DomainName : ZString;
 DomainNameLength : DWORD;
 Name : ZString;
 NameLength : DWORD;
begin
 if not LookupAccountSid(nil, SID, Name, NameLength, DomainName,
    DomainNameLength, Use) then
   RaiseLastWin32Error;
 Result := Name;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 AccessToken : THandle;
 Info : PSIDANDATTRIBUTES;
 ReturnLength : DWORD;
begin
 Win32Check(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, AccessToken));
 GetMem (Info, 1024);
 try
   Win32Check(GetTokenInformation(AccessToken, TokenUser, Info, 1024,
     ReturnLength));
   ShowMessage(SidToName(Info^.Sid));
 finally
   FreeMem(Info);
 end;
end;

end.


Может, поможет...


VMcL   (2004-04-13 14:37:00) [11]

>>Alexis ©  (13.04.04 13:48) [5]

Используй лучше RaiseLastOSError, а не просто отображение номера ошибки.


Alexis   (2004-04-13 14:09:00) [12]

Ага, вот оно что.
Ну а что насчет предопределенной константы?


VMcL   (2004-04-13 14:06:00) [13]

{ The data area passed to a system call is too small. }
 ERROR_INSUFFICIENT_BUFFER = 122;   { dderror }


Alexis   (2004-04-13 13:48:00) [14]

2 Игорь Шевченко-спасибо, я узнал из ссылки [1].

Попытался написать код с использованием этих ф-ций:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls,
 TLHelp32,
 psAPI;

type
 TForm1 = class(TForm)
   Button1: TButton;
   ListBox1: TListBox;
   ListBox2: TListBox;
   Label1: TLabel;
   Label2: TLabel;
   Button2: TButton;
   ListBox3: TListBox;
   Button3: TButton;
   ListBox4: TListBox;
   procedure Button3Click(Sender: TObject);

 private
 public
   { Public declarations }
 end;

type SID_AND_ATTRIBUTES = record
  Sid: Pointer;
  Attributes:DWORD ;
end;

type TOKEN_USER = record
   SID_AND_ATTRIBUTES: DWORD;
end;

var
 Form1: TForm1;
 activePIDS : TList;
 TU: TOKEN_USER;

implementation

{$R *.dfm}

procedure TForm1.Button3Click(Sender: TObject);
var
snapshot : Cardinal;
procInfo : PROCESSENTRY32;
procInfoW : PROCESSENTRY32W;
procHandle, hMod : THandle;
BytesReturned : Cardinal;
pathsize : Cardinal;
j,k : integer;
pathname : array [0..1000] of char;

buff, buff2:string;
cp:Cardinal;

PID, size : DWORD;
TokenHandle : THandle;

begin
ListBox1.Clear;
ListBox2.Clear;
ListBox4.Clear;

snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
procInfo.dwSize := sizeof(procInfo);

if Process32First(snapshot, procInfo) then
 repeat
  ListBox1.Items.Add(strpas(procInfo.szExeFile) + ' ID: ' + inttostr(procInfo.th32ProcessID));
  procHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, procInfo.th32ProcessID);

  if procHandle<>0 then
   begin
    OpenProcessToken(procHandle, TOKEN_QUERY, TokenHandle);
    size := sizeof(TOKEN_USER);

    if GetTokenInformation(TokenHandle, TokenUser,@TU,SizeOf(TOKEN_USER),Size) then
     ListBox4.Items.Add('information was successfully retrieved')
    else
     ListBox4.Items.Add('Error:'+IntToStr(GetLastError));
   
    EnumProcessModules(procHandle, @hmod, sizeof(THandle), BytesReturned);
    GetModuleFileNameEx(procHandle, hmod, pathname, sizeof(pathname));
    ListBox2.Items.Add( strpas(pathname) );
   end
  else
   ListBox2.Items.Add('-system process-');

  closeHandle(procHandle);
 until not Process32Next(snapshot, procInfo);

end;

end.

На что мне в ListBox4 ко всем процессам, к которым удалось получить handle прописывается Error 122.
Что не так я делаю?
Кстати, есть ли какая-нибудь предопределенная константа, идентифицирующая системный процесс, типа SYSTEM_PROCESS ?


Игорь Шевченко   (2004-04-10 21:12:00) [15]


> Признак системности - по-моему - по id пользователя


OpenProcessToken + GetTokenInformation


Alexis   (2004-04-10 19:49:00) [16]


> Признак системности - по-моему - по id пользователя (Видели,
> наверное - User Name = "NT AUTHORITY/SYSTEM")

Не видел. Можно поподробнее?


Cobalt   (2004-04-10 19:40:00) [17]

Имя разработчика берётся из ресурсов.
Признак системности - по-моему - по id пользователя (Видели, наверное - User Name = "NT AUTHORITY/SYSTEM")


BiN   (2004-04-10 19:37:00) [18]

как точно определить что процесс системный

- по имени пользователя процесса
см. http://www.delphimaster.ru/cgi-bin/forum.pl?id=1080802082&n=5

Process Explorer(на SysInternals.com) как-то определяет, кто разработчик программы (к процессам из директории Windows прописывает Microsoft Corporation.)
С помощью каких ф-ций это узнается?


GetFileVersionInfo и иже с ним.

Нужны ли Debug привилегии?

нет


Наверх

Титульная страница Поиск, карта сайта Написать письмо