2013-10-29 30 views
0

我实际上编程的应用程序看到什么文件打开德尔福 - 通过使用句柄的进程获取打开的文件

他是不是由我的代码的一部分,我试图使用它,但我不明白它... 我想获取由进程打开的文件名,但该函数总是导致这样的:/默认或/会话/ 1/Windows的 ...像that.Please东西帮助我,对不起我的英文不好

const 
SystemHandleInformation = $10; 
STATUS_SUCCESS = $00000000; 
STATUS_BUFFER_OVERFLOW = $80000005; 
STATUS_INFO_LENGTH_MISMATCH = $C0000004; 
DefaulBUFFERSIZE = $100000; 

type 
OBJECT_INFORMATION_CLASS = (ObjectBasicInformation, ObjectNameInformation, 
ObjectTypeInformation, ObjectAllTypesInformation, ObjectHandleInformation); 

SYSTEM_HANDLE = packed record 
uIdProcess: ULONG; 
ObjectType: UCHAR; 
Flags: UCHAR; 
Handle: Word; 
pObject: Pointer; 
GrantedAccess: ACCESS_MASK; 
end; 

PSYSTEM_HANDLE = ^SYSTEM_HANDLE; 
SYSTEM_HANDLE_ARRAY = Array [0 .. 0] of SYSTEM_HANDLE; 
PSYSTEM_HANDLE_ARRAY = ^SYSTEM_HANDLE_ARRAY; 

SYSTEM_HANDLE_INFORMATION = packed record 
uCount: ULONG; 
Handles: SYSTEM_HANDLE_ARRAY; 
end; 

PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION; 

TNtQuerySystemInformation = function(SystemInformationClass: DWORD; 
SystemInformation: Pointer; SystemInformationLength: DWORD; 
ReturnLength: PDWORD): THandle; stdcall; 
TNtQueryObject = function(ObjectHandle: cardinal; 
ObjectInformationClass: OBJECT_INFORMATION_CLASS; 
ObjectInformation: Pointer; Length: ULONG; ResultLength: PDWORD) 
: THandle; stdcall; 

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

OBJECT_NAME_INFORMATION = UNICODE_STRING; 
POBJECT_NAME_INFORMATION = ^OBJECT_NAME_INFORMATION; 

Var 
NTQueryObject: TNtQueryObject; 
NTQuerySystemInformation: TNtQuerySystemInformation; 


Procedure EnumerateOpenFiles(); 
var 
sDummy: string; 
hProcess: THandle; 
hObject: THandle; 
ResultLength: DWORD; 
aBufferSize: DWORD; 
aIndex: Integer; 
pHandleInfo: PSYSTEM_HANDLE_INFORMATION; 
HDummy: THandle; 
lpwsName: PWideChar; 
lpwsType: PWideChar; 
lpszProcess: pchar; 
begin 
aBufferSize := DefaulBUFFERSIZE; 
pHandleInfo := AllocMem(aBufferSize); 
HDummy := NTQuerySystemInformation(DWORD(SystemHandleInformation), 
pHandleInfo, aBufferSize, @ResultLength); // Get the list of handles 

if (HDummy = STATUS_SUCCESS) then // If no error continue 
begin 

for aIndex := 0 to pHandleInfo^.uCount - 1 do // iterate the list 
begin 
    hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or 
    PROCESS_VM_READ, False, pHandleInfo.Handles[aIndex].uIdProcess); 
    // open the process to get aditional info 
    if (hProcess <> INVALID_HANDLE_VALUE) then // Check valid handle 
    begin 

    hObject := 0; 
    if DuplicateHandle(hProcess, pHandleInfo.Handles[aIndex].Handle, 
     GetCurrentProcess, @hObject, STANDARD_RIGHTS_REQUIRED, False, 0) then 
    // Get a copy of the original handle 
    begin 

     lpwsName := GetObjectInfo(hObject, ObjectTypeInformation); 

     // Get the filename linked to the handle 
     if (lpwsName <> nil) then 
     begin 
     lpwsType := GetObjectInfo(hObject, ObjectNameInformation); 
     lpszProcess := AllocMem(MAX_PATH); 

     if GetModuleFileNameEx(hProcess, 0, lpszProcess, MAX_PATH) <> 0 then 
      // get the name of the process 
      sDummy := ExtractFileName(lpszProcess) 
     else 
      sDummy := 'System Process'; 


      with MainForm.UsedFilesListView.Items.add do 
      begin 

      // Ajout 
      Caption := sDummy; 

      ImageIndex := -1; 

      SubItems.add(lpwsName); 

      end; 


     // Writeln('PID  ', pHandleInfo.Handles[aIndex].uIdProcess); 
     // Writeln('Handle ', pHandleInfo.Handles[aIndex].Handle); 
     // Writeln('Process ', sDummy); 
     // Writeln('FileName ', string(lpwsName)); 
     // Writeln; 

     FreeMem(lpwsName); 
     FreeMem(lpwsType); 
     FreeMem(lpszProcess); 
     end; 
     CloseHandle(hObject); 
    end; 
    CloseHandle(hProcess); 
    end; 
end; 
end; 
FreeMem(pHandleInfo); 

end; 
+0

我们无法运行此代码。如果您发布了我们可以运行的完整SSCCE,那对我们来说肯定会更容易?由于我们无法运行它,并且由于您在标题翻译中使用了非标准术语,所以我们甚至不知道此代码的功能。什么是SystemHandleInformation?我们可以猜测,但我们不应该这样做。 –

+0

你应该问的问题是,“我如何列举所有打开的文件句柄?” –

+1

Omg我只是问如何转换路径Session \ 1 \ WIndows ...为什么你进取 – user2785119

回答

2

首先,您未能在您的问题中提供SSCCE,这大大降低了某人查看并尝试修复代码的机会。因为我们需要考虑所有缺少的声明和需要包含哪些单元来编写可编译代码,是的,那很无聊。

其次,copy and paste programming是不好的做法,它不会让你的编程技能提高。尝试咨询MSDN了解某些API的用途以及如何使用它们,然后尝试使用通过Google/MSDN收集的信息来摆弄代码。

关于问题本身,这是一个棘手的问题,并且广泛无证。

在SysInternals论坛上查看这个有用的帖子,大致解释了你必须做的事情:HOWTO: Enumerate handles

获取文件路径后,您必须用其映射路径替换MS-DOS设备路径(例如\Device\HarddiskVolume1>C:\)。您可以使用GetLogicalDriveStringsQueryDosDevice API来完成此操作。

现在的代码本身。你需要JEDI API library来编译它。在XE2上测试:

{$APPTYPE CONSOLE} 

program FileHandles; 

uses 
    Winapi.Windows, 
    System.Classes, 
    JwaNative, 
    JwaNtStatus, 
    JwaWinternl; 

procedure EnumerateDevicePaths(const ADeviceNames, ADevicePaths: TStringList); 
var 
    drives  : array[0..4095] of Char; 
    pdrive  : PChar; 
    drive  : String; 
    drive_path : array[0..4095] of Char; 
    sdrive_path: String; 
begin 
    ADeviceNames.Clear; 
    ADevicePaths.Clear; 

    if GetLogicalDriveStrings(SizeOf(drives), drives) = 0 then 
    Exit; 

    pdrive := drives; 
    while pdrive^ <> #0 do 
    begin 
    drive := Copy(pdrive, 0, 4); 
    if drive <> '' then 
    begin 
     if drive[Length(drive)] = '\' then 
     Delete(drive, Length(drive), 1); 

     QueryDosDevice(PChar(drive), drive_path, SizeOf(drive_path)); 
     sdrive_path := drive_path; 

     ADeviceNames.Add(drive); 
     ADevicePaths.Add(sdrive_path); 
    end; 
    Inc(pdrive, 4); 
    end; 
end; 

function EnumerateOpenFiles: Integer; 
const 
    HANDLE_BUFFER_INCREASE_CHUNK = 16 * 1024; // increase handles buffer by 16kb 
type 
    // this struct is missing in JEDI declarations (?) 
    TSystemHandleInformations = record 
    HandleCount: ULONG; 
    Handles : array[0..0] of TSystemHandleInformation; 
    end; 
    PSystemHandleInformations = ^TSystemHandleInformations; 
var 
    phandles_info : PSystemHandleInformations; 
    phandles_size : DWORD; 
    retcode  : DWORD; 
    C1, C2  : Integer; 
    phandle_info : PSystemHandleInformation; 
    process_handle: THandle; 
    dup_handle : THandle; 
    obj_name_info : PObjectNameInformation; 
    obj_name_size : DWORD; 
    fname   : String; 
    device_names : TStringList; 
    device_paths : TStringList; 
begin 
    device_names := TStringList.Create; 
    try 
    device_paths := TStringList.Create; 
    try 
     EnumerateDevicePaths(device_names, device_paths); // enumerate devices list, so we can use these later on to replace MS-DOS paths with mapped ones 

     phandles_size := HANDLE_BUFFER_INCREASE_CHUNK; // start with HANDLE_BUFFER_INCREASE_CHUNK value 
     phandles_info := AllocMem(phandles_size); 
     try 
     retcode := NtQuerySystemInformation(DWORD(SystemHandleInformation), phandles_info, phandles_size, nil); 
     while retcode = STATUS_INFO_LENGTH_MISMATCH do // realloc handles buffer memory until it's big enough to accept all handles data 
     begin 
      Inc(phandles_size, HANDLE_BUFFER_INCREASE_CHUNK); 
      ReallocMem(phandles_info, phandles_size); 
      retcode := NtQuerySystemInformation(DWORD(SystemHandleInformation), phandles_info, phandles_size, nil); 
     end; 

     if retcode <> STATUS_SUCCESS then 
      Exit(retcode); 

     // iterate through opened handles 
     for C1 := 0 to phandles_info^.HandleCount do 
     begin 
      phandle_info := pointer(Integer(@phandles_info^.Handles) + C1 * SizeOf(TSystemHandleInformation)); // get pointer to C1 handle info structure 

      // if ObjectType is not file, or if handle is named pipe (which would make Nt*() function to block), we skip to the next handle 
      // GrantedAccess mask here is very cryptic, I've been unable to find more information about it on Google, all codes use static hex numbers for check 
      if (phandle_info^.ObjectTypeNumber <> 28) or 
      (phandle_info^.GrantedAccess = $0012019F) or 
      (phandle_info^.GrantedAccess = $001A019F) or 
      (phandle_info^.GrantedAccess = $00120189) then 
      Continue; 

      process_handle := OpenProcess(PROCESS_DUP_HANDLE, FALSE, phandle_info^.ProcessId); 
      if process_handle <> 0 then 
      try 
      if DuplicateHandle(process_handle, phandle_info^.Handle, GetCurrentProcess, @dup_handle, 0, FALSE, 0) then 
      try 
       obj_name_size := SizeOf(TObjectNameInformation); 
       obj_name_info := AllocMem(obj_name_size); 
       try 
       // get path to the file 
       retcode := NtQueryObject(dup_handle, ObjectNameInformation, obj_name_info, obj_name_size, @obj_name_size); 
       if retcode <> STATUS_SUCCESS then 
       begin 
        ReallocMem(obj_name_info, obj_name_size); 
        retcode := NtQueryObject(dup_handle, ObjectNameInformation, obj_name_info, obj_name_size, nil); 
       end; 

       if retcode <> STATUS_SUCCESS then 
        Continue; 

       fname := obj_name_info^.Name.Buffer; 

       // replace MS-DOS device names with their mappings 
       for C2 := 0 to device_paths.Count - 1 do 
        if Copy(fname, 1, Length(device_paths[C2])) = device_paths[C2] then 
        begin 
        Delete(fname, 1, Length(device_paths[C2])); 
        fname := device_names[C2] + fname; 
        Break; 
        end; 

       // do necessary processing with fname here 
       WriteLn(phandle_info^.ProcessId, ': ', fname); 
       finally 
       FreeMem(obj_name_info, obj_name_size); 
       end; 
      finally 
       CloseHandle(dup_handle); 
      end; 
      finally 
      CloseHandle(process_handle); 
      end; 
     end; 
     finally 
     FreeMem(phandles_info, phandles_size); 
     end; 

     Exit(STATUS_SUCCESS); 
    finally 
     device_paths.Free; 
    end; 
    finally 
    device_names.Free; 
    end; 
end; 

begin 
    EnumerateOpenFiles; 
    Write('Done!'); 
    ReadLn; 
end. 

该代码可以在几种方式上得到改进,但我给了你足够的启动。例如,其中一个优化是避免通过按PID排序句柄列表多次打开相同的进程,然后仅打开一次进程来检查具有相同PID的句柄组。

0

看来,您使用的代码从这里:Delphi - get what files are opened by an application。该代码声称:

名单从所有进程

换句话说,它列出了与比文件对象的其他对象相关处理所有打开的句柄。你看到的不像文件名的文件名确实如此。它们是进程所处理的文件以外的对象的名称。

+0

那么如何获取文件对象呢? :(我有句柄,但是我不能将它们转换成文件名? – user2785119

+0

你确实有文件对象,它们也被枚举,但是你也列举了其他对象的代码 –

+0

在这个问题中的代码是非常糟糕和过时的 –