Получаю файлы, открытые процессом:
1. Получаю перечень всех открытых хэндлов в системе при помощи ZwQuerySystemInformation
2. В цикле сравниваю ProcessId открытых хэндлов с PID нужного процесса. Если они равны, и если тип объекта — файл, получаю имя файла.
Суть проблемы: PID, которые больше определенного значения (у меня это 65212), не находится в списке ProcessId открытых хэндлов (просто нет хэндлов с нужным ProcessId).
Не подскажете, с чем это связано и как это побороть?
Хотя, к примеру тот же ProcessExplorer отображает хэндлы всех процессов нормально..
Re: не находится ProcessId в SystemHandleInformation
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>скажу честно, сейчас не проверял, но лет 5 назад работало... OAB>странно, может какие ньюансы? обычное приложение? не сервис? ничего такого?
Обычное приложение. Да оно нормально работает за исключением тех процессов, PID у которых больше 65212. При этом в перечень хэндлов попадают такие, у которых ProcessId вообще нет в списке запущенных процессов. Такое впечатление, что ProcessId > 65212 просто обрезаются либо каким-то образом преобразуются, хотя в структуре SystemHandleInformation у ProcessId тип DWord, вроде бы должно хватать...
Re[5]: не находится ProcessId в SystemHandleInformation
Здравствуйте, 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