не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 24.01.07 01:58
Оценка:
Получаю файлы, открытые процессом:
1. Получаю перечень всех открытых хэндлов в системе при помощи ZwQuerySystemInformation
2. В цикле сравниваю ProcessId открытых хэндлов с PID нужного процесса. Если они равны, и если тип объекта — файл, получаю имя файла.

Суть проблемы: PID, которые больше определенного значения (у меня это 65212), не находится в списке ProcessId открытых хэндлов (просто нет хэндлов с нужным ProcessId).
Не подскажете, с чем это связано и как это побороть?

Хотя, к примеру тот же ProcessExplorer отображает хэндлы всех процессов нормально..
Re: не находится ProcessId в SystemHandleInformation
От: Oleg A. Bachin Украина  
Дата: 25.01.07 07:55
Оценка:
Здравствуйте, paulbc, Вы писали:

http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827
Best regards,
Oleg A. Bachin
Re[2]: не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 25.01.07 23:43
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>Здравствуйте, paulbc, Вы писали:


OAB>http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827


Спасибо за ответ, но я там уже был. Фактически там используется такой же метод, что и у меня и с теми же проблемами. К сожалению..
Re[3]: не находится ProcessId в SystemHandleInformation
От: Oleg A. Bachin Украина  
Дата: 26.01.07 09:41
Оценка:
Здравствуйте, paulbc, Вы писали:

OAB>>http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827


P>Спасибо за ответ, но я там уже был. Фактически там используется такой же метод, что и у меня и с теми же проблемами. К сожалению..


скажу честно, сейчас не проверял, но лет 5 назад работало...
странно, может какие ньюансы? обычное приложение? не сервис? ничего такого?
Best regards,
Oleg A. Bachin
Re[4]: не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 26.01.07 09:58
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>скажу честно, сейчас не проверял, но лет 5 назад работало...

OAB>странно, может какие ньюансы? обычное приложение? не сервис? ничего такого?

Обычное приложение. Да оно нормально работает за исключением тех процессов, PID у которых больше 65212. При этом в перечень хэндлов попадают такие, у которых ProcessId вообще нет в списке запущенных процессов. Такое впечатление, что ProcessId > 65212 просто обрезаются либо каким-то образом преобразуются, хотя в структуре SystemHandleInformation у ProcessId тип DWord, вроде бы должно хватать...
Re[5]: не находится ProcessId в SystemHandleInformation
От: Oleg A. Bachin Украина  
Дата: 26.01.07 10:30
Оценка:
Здравствуйте, paulbc, Вы писали:

что еще делать, закидывай код — посмотрим
Best regards,
Oleg A. Bachin
Re[6]: не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 26.01.07 13:07
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>Здравствуйте, paulbc, Вы писали:


OAB>что еще делать, закидывай код — посмотрим


как-то вот так:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

type
  NTStatus = cardinal;

CONST  //Статус константы
  STATUS_SUCCESS              = NTStatus($00000000);
  STATUS_ACCESS_DENIED        = NTStatus($C0000022);
  STATUS_INFO_LENGTH_MISMATCH = NTStatus($C0000004);
  SEVERITY_ERROR              = NTStatus($C0000000);

type
PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;
SYSTEM_HANDLE_INFORMATION = packed record
   ProcessId: dword;
   ObjectTypeNumber: byte;
   Flags: byte;
   Handle: word;
   pObject: pointer;
   GrantedAccess: dword;
   end;

PSYSTEM_HANDLE_INFORMATION_EX = ^SYSTEM_HANDLE_INFORMATION_EX;
SYSTEM_HANDLE_INFORMATION_EX = packed record
   NumberOfHandles: dword;
   Information: array [0..0] of SYSTEM_HANDLE_INFORMATION;
   end;

const
  ObjectNameInformation = 1;

type
  UNICODE_STRING = packed record
    Length: Word; 
    MaximumLength: Word; 
    Buffer: PWideChar; 
end; 

type
  OBJECT_NAME_INFORMATION = record
   Name: UNICODE_STRING; 
end;

Function NtQuerySystemInformation(ASystemInformationClass: dword;
                                  ASystemInformation: Pointer;
                                  ASystemInformationLength: dword;
                                  AReturnLength:PCardinal): NTStatus;
                                  stdcall;external 'ntdll.dll';

function NtQueryObject(ObjectHandle,
                        ObjectInformationClass: Integer;
                        ObjectInformation: Pointer;
                        Length: Integer;
                        var ResultLength: Integer): Integer;
                        stdcall; external 'ntdll.dll';

{ Получение буфера с системной информацией }
Function GetInfoTable(ATableType:dword):Pointer;
var
 mSize: dword;
 mPtr: pointer;
 St: NTStatus;
begin
 Result := nil;
 mSize := $4000; //начальный размер буффера
 repeat
   mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
   if mPtr = nil then Exit;
   St := NtQuerySystemInformation(ATableType, mPtr, mSize, nil);
   if St = STATUS_INFO_LENGTH_MISMATCH then
      begin //надо больше памяти
        VirtualFree(mPtr, 0, MEM_RELEASE);
        mSize := mSize * 2;
      end;
 until St <> STATUS_INFO_LENGTH_MISMATCH;
 if St = STATUS_SUCCESS
   then Result := mPtr
   else VirtualFree(mPtr, 0, MEM_RELEASE);
end;

function GetFileNameAndPathFromHandle(const hFile: THandle): string;
var
  sName: string;
  ret: Integer;
  struct: ^OBJECT_NAME_INFORMATION;
  st: NTStatus;
  Temp : array [0..511] of char;
  FileName : array [0..MAX_PATH] of char;
  Name : array [0..MAX_PATH-1] of char;
  Drive : array [0..2] of char;
  p : PChar;
  found : boolean;
  NameLen : integer;
  i: integer;
begin
  result := '';
  GetMem(struct, MAX_PATH * SizeOf(WCHAR));
  try
    st := NtQueryObject(hFile, ObjectNameInformation, struct,
                        MAX_PATH * SizeOf(WCHAR), ret);
    if st = STATUS_SUCCESS then
    begin
      sName := WideCharToString(struct^.name.buffer);
      FillChar(FileName, MAX_PATH, #0);
      for i := 1 to StrLen(PChar(sName)) do
        FileName[i-1] := sName[i];
        if GetLogicalDriveStrings(SizeOf(Temp), @temp) <> 0 then
          begin
              Drive := ' :'#0;
              found := false;
              p := @Temp;
              repeat
                  Drive[0] := p^;
                  if (QueryDosDevice(@Drive, Name, sizeOf(Name)) <> 0) then
                  begin
                      NameLen := Length(PChar(@Name));
                      found := (Pos(Name, FileName) = 1);
                      if found then begin
                          sName := Drive+Copy(FileName,NameLen+1,Length(PChar(@FileName))-NameLen);
            end;
                  end;
                  while (p^ <> #0) do inc(cardinal(p));
          inc(cardinal(p));
        until found or (p^ = #0);
      end;
      result := sName;
    end;
  finally
    FreeMem(struct);
  end;
end;


var
  HandlesInfo: PSYSTEM_HANDLE_INFORMATION_EX;
  fName, s: string;
  r: integer;
  fHandle, fHandle2, pHandle: THandle;
  pid: DWord;

begin
  //if paramcount < 1 then begin
    writeln('enter the pid');
    readln(s);
  //end else
    //s := paramstr(1);

  try
    pid := strtoint(s);
  except
    writeln('incorrect pid');
    readln;
    exit;
  end;
  HandlesInfo := GetInfoTable(16);
  try
  if HandlesInfo = nil then begin
    writeln('HandlesInfo = nil');
    exit;
  end;
  for r := 0 to HandlesInfo^.NumberOfHandles-1 do begin
    if HandlesInfo^.Information[r].ProcessId = pid then begin
      if HandlesInfo^.Information[r].ObjectTypeNumber = 28 then
      begin
        fName := '';
        pHandle := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
        if pHandle = 0 then begin
          writeln('open process errror: '+inttostr(getlasterror));
          readln;
          exit;
        end;
        if pHandle <> 0 then begin
          fHandle := HandlesInfo^.Information[r].Handle;
          if DuplicateHandle(pHandle, fHandle, GetCurrentProcess, @fHandle2,
                              0, false, DUPLICATE_SAME_ACCESS) then
          begin
            fName := '';
            try
              fName := GetFileNameAndPathFromHandle(fHandle2);
            except
              on E: Exception do fName := E.Message;
            end;
            CloseHandle(fHandle2);
            writeln('process id: '+inttostr(pid)+
                    ' handle: '+inttostr(fhandle)+
                    ' file: '+ fName);
          end else writeln('DuplicateHandle error: '+inttostr(getlasterror));
          CloseHandle(pHandle);
        end;
      end;
    end;
  end;
  finally
    VirtualFree(HandlesInfo, 0, MEM_RELEASE);
  end;
  readln;
end.
Re: не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 31.01.07 01:22
Оценка:
up?
Вопрос все еще актуален.
Re[2]: не находится ProcessId в SystemHandleInformation
От: Danchik Украина  
Дата: 31.01.07 14:05
Оценка:
Здравствуйте, paulbc, Вы писали:

P>up?

P>Вопрос все еще актуален.

Советую задать этот вопрос в WinAPI форуме.
Re: не находится ProcessId в SystemHandleInformation
От: paulbc  
Дата: 01.02.07 01:04
Оценка:
Всем спасибо, проблема решена приведением искомого PID к типу Word.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.