Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как узнать все открытые дескрипторы файлов?

01.01.2007
////////////////////////////////////////////////////////////////////////////////
//
//  ****************************************************************************
//  * Unit Name : Unit15
//  * Purpose   : Перечисление всех открытых файлов в системе
//  *             (до которых получилось достучаться)
//  * Author    : Александр (Rouse_) Багель
//  * Version   : 1.00
//  ****************************************************************************
//

 
 
unit Unit15
;
 
interface
 
uses
 
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 
Dialogs, StdCtrls, ComCtrls;
 
type
  TForm15
= class(TForm)
    Button1
: TButton;
    Memo1
: TMemo;
    ProgressBar1
: TProgressBar;
    procedure Button1Click
(Sender: TObject);
 
public
    procedure
ShowLockedProcess(FileName: String);
 
end;
 
var
  Form15
: TForm15;
 
implementation
 
{$R *.dfm}
 
type
  NT_STATUS
= Cardinal;
 
 
TFileDirectoryInformation = packed record
   
NextEntryOffset: ULONG;
   
FileIndex: ULONG;
   
CreationTime: LARGE_INTEGER;
   
LastAccessTime: LARGE_INTEGER;
   
LastWriteTime: LARGE_INTEGER;
   
ChangeTime: LARGE_INTEGER;
   
EndOfFile: LARGE_INTEGER;
   
AllocationSize: LARGE_INTEGER;
   
FileAttributes: ULONG;
   
FileNameLength: ULONG;
   
FileName: array[0..0] of WideChar;
 
end;
  FILE_DIRECTORY_INFORMATION
= TFileDirectoryInformation;
 
PFileDirectoryInformation = ^TFileDirectoryInformation;
  PFILE_DIRECTORY_INFORMATION
= PFileDirectoryInformation;
 
  PSYSTEM_THREADS
= ^SYSTEM_THREADS;
  SYSTEM_THREADS  
= packed record
   
KernelTime: LARGE_INTEGER;
   
UserTime: LARGE_INTEGER;
   
CreateTime: LARGE_INTEGER;
   
WaitTime: ULONG;
   
StartAddress: Pointer;
   
UniqueProcess: DWORD;
   
UniqueThread: DWORD;
   
Priority: Integer;
   
BasePriority: Integer;
   
ContextSwitchCount: ULONG;
   
State: Longint;
   
WaitReason: Longint;
 
end;
 
  PSYSTEM_PROCESS_INFORMATION
= ^SYSTEM_PROCESS_INFORMATION;
  SYSTEM_PROCESS_INFORMATION
= packed record
   
NextOffset: ULONG;
   
ThreadCount: ULONG;
    Reserved1
: array [0..5] of ULONG;
   
CreateTime: FILETIME;
   
UserTime: FILETIME;
   
KernelTime: FILETIME;
   
ModuleNameLength: WORD;
   
ModuleNameMaxLength: WORD;
   
ModuleName: PWideChar;
   
BasePriority: ULONG;
   
ProcessID: ULONG;
   
InheritedFromUniqueProcessID: ULONG;
   
HandleCount: ULONG;
    Reserved2
: array[0..1] of ULONG;
   
PeakVirtualSize : ULONG;
   
VirtualSize : ULONG;
   
PageFaultCount : ULONG;
   
PeakWorkingSetSize : ULONG;
   
WorkingSetSize : ULONG;
   
QuotaPeakPagedPoolUsage : ULONG;
   
QuotaPagedPoolUsage : ULONG;
   
QuotaPeakNonPagedPoolUsage : ULONG;
   
QuotaNonPagedPoolUsage : ULONG;
   
PageFileUsage : ULONG;
   
PeakPageFileUsage : ULONG;
   
PrivatePageCount : ULONG;
   
ReadOperationCount : LARGE_INTEGER;
   
WriteOperationCount : LARGE_INTEGER;
   
OtherOperationCount : LARGE_INTEGER;
   
ReadTransferCount : LARGE_INTEGER;
   
WriteTransferCount : LARGE_INTEGER;
   
OtherTransferCount : LARGE_INTEGER;
   
ThreadInfo: array [0..0] of SYSTEM_THREADS;
 
end;
 
  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;
 
  PFILE_NAME_INFORMATION
= ^FILE_NAME_INFORMATION;
  FILE_NAME_INFORMATION
= packed record
   
FileNameLength: ULONG;
   
FileName: array [0..MAX_PATH - 1] of WideChar;
 
end;
 
  PUNICODE_STRING
= ^TUNICODE_STRING;
  TUNICODE_STRING
= packed record
   
Length : WORD;
   
MaximumLength : WORD;
   
Buffer : array [0..MAX_PATH - 1] of WideChar;
 
end;
 
  POBJECT_NAME_INFORMATION
= ^TOBJECT_NAME_INFORMATION;
  TOBJECT_NAME_INFORMATION
= packed record
   
Name : TUNICODE_STRING;
 
end;
 
  PIO_STATUS_BLOCK
= ^IO_STATUS_BLOCK;
  IO_STATUS_BLOCK
= packed record
   
Status: NT_STATUS;
   
Information: DWORD;
 
end;
 
 
PGetFileNameThreadParam = ^TGetFileNameThreadParam;
 
TGetFileNameThreadParam = packed record
    hFile
: THandle;
   
Data: array [0..MAX_PATH - 1] of Char;
   
Status: NT_STATUS;
 
end;
 
const
  STATUS_SUCCESS
= NT_STATUS($00000000);
  STATUS_INVALID_INFO_CLASS
= NT_STATUS($C0000003);
  STATUS_INFO_LENGTH_MISMATCH
= NT_STATUS($C0000004);
  STATUS_INVALID_DEVICE_REQUEST
= NT_STATUS($C0000010);
 
ObjectNameInformation = 1;
 
FileDirectoryInformation = 1;
 
FileNameInformation = 9;
 
SystemProcessesAndThreadsInformation = 5;
 
SystemHandleInformation = 16;
 
 
function ZwQuerySystemInformation(ASystemInformationClass: DWORD;
   
ASystemInformation: Pointer; ASystemInformationLength: DWORD;
   
AReturnLength: PDWORD): NT_STATUS; stdcall; external 'ntdll.dll';
 
 
function NtQueryInformationFile(FileHandle: THandle;
   
IoStatusBlock: PIO_STATUS_BLOCK; FileInformation: Pointer;
   
Length: DWORD; FileInformationClass: DWORD): NT_STATUS;
    stdcall
; external 'ntdll.dll';
 
 
function NtQueryObject(ObjectHandle: THandle;
   
ObjectInformationClass: DWORD; ObjectInformation: Pointer;
   
ObjectInformationLength: ULONG;
   
ReturnLength: PDWORD): NT_STATUS; stdcall; external 'ntdll.dll';
 
 
function GetLongPathNameA(lpszShortPath, lpszLongPath: PChar;
    cchBuffer
: DWORD): DWORD; stdcall; external kernel32;
 
procedure TForm15
.Button1Click(Sender: TObject);
begin
 
ShowLockedProcess('');
end;
 
procedure TForm15
.ShowLockedProcess(FileName: String);
 
 
function GetInfoTable(ATableType: DWORD): Pointer;
 
var
    dwSize
: DWORD;
    pPtr
: Pointer;
    ntStatus
: NT_STATUS;
 
begin
   
Result := nil;
    dwSize
:= WORD(-1);
   
GetMem(pPtr, dwSize);
    ntStatus
:= ZwQuerySystemInformation(ATableType, pPtr, dwSize, nil);
   
while ntStatus = STATUS_INFO_LENGTH_MISMATCH do
   
begin
      dwSize
:= dwSize * 2;
     
ReallocMem(pPtr, dwSize);
      ntStatus
:= ZwQuerySystemInformation(ATableType, pPtr, dwSize, nil);
   
end;
   
if ntStatus = STATUS_SUCCESS then
     
Result := pPtr
   
else
     
FreeMem(pPtr);
 
end;
 
 
function GetFileNameThread(lpParameters: Pointer): DWORD; stdcall;
 
var
   
FileNameInfo: FILE_NAME_INFORMATION;
   
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
   
IoStatusBlock: IO_STATUS_BLOCK;
    pThreadParam
: TGetFileNameThreadParam;
    dwReturn
: DWORD;
 
begin
   
ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
    pThreadParam
:= PGetFileNameThreadParam(lpParameters)^;
   
Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,
     
@FileNameInfo, MAX_PATH * 2, FileNameInformation);
   
if Result = STATUS_SUCCESS then
   
begin
     
Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,
       
@ObjectNameInfo, MAX_PATH * 2, @dwReturn);
     
if Result = STATUS_SUCCESS then
     
begin
        pThreadParam
.Status := Result;
       
WideCharToMultiByte(CP_ACP, 0,
         
@ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength -
         
ObjectNameInfo.Name.Length],
         
ObjectNameInfo.Name.Length, @pThreadParam.Data[0],
          MAX_PATH
, nil, nil);
     
end
     
else
     
begin
        pThreadParam
.Status := STATUS_SUCCESS;
       
Result := STATUS_SUCCESS;
       
WideCharToMultiByte(CP_ACP, 0,
         
@FileNameInfo.FileName[0], IoStatusBlock.Information,
          @pThreadParam
.Data[0],
          MAX_PATH
, nil, nil);
     
end;
   
end;
   
PGetFileNameThreadParam(lpParameters)^ := pThreadParam;
   
ExitThread(Result);
 
end;
 
 
function GetFileNameFromHandle(hFile: THandle): String;
 
var
    lpExitCode
: DWORD;
    pThreadParam
: TGetFileNameThreadParam;
    hThread
: THandle;
 
begin
   
Result := '';
   
ZeroMemory(@pThreadParam, SizeOf(TGetFileNameThreadParam));
    pThreadParam
.hFile := hFile;
    hThread
:= CreateThread(nil, 0, @GetFileNameThread, @pThreadParam, 0, PDWORD(nil)^);
   
if hThread <> 0 then
   
try
     
case WaitForSingleObject(hThread, 100) of
        WAIT_OBJECT_0
:
       
begin
         
GetExitCodeThread(hThread, lpExitCode);
         
if lpExitCode = STATUS_SUCCESS then
           
Result := pThreadParam.Data;
       
end;
        WAIT_TIMEOUT
:
         
TerminateThread(hThread, 0);
     
end;
   
finally
     
CloseHandle(hThread);
   
end;
 
end;
 
 
function SetDebugPriv: Boolean;
 
var
   
Token: THandle;
    tkp
: TTokenPrivileges;
 
begin
   
Result := false;
   
if OpenProcessToken(GetCurrentProcess,
      TOKEN_ADJUST_PRIVILEGES
or TOKEN_QUERY, Token) then
   
begin
     
if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'),
        tkp
.Privileges[0].Luid) then
     
begin
        tkp
.PrivilegeCount := 1;
        tkp
.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
       
Result := AdjustTokenPrivileges(Token, False,
          tkp
, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
     
end;
   
end;
 
end;
 
type
 
DriveQueryData = record
   
DiskLabel: String;
   
DiskDosQuery: String;
   
DosQueryLen: Integer;
 
end;
 
var
  hFile
, hProcess: THandle;
  pHandleInfo
: PSYSTEM_HANDLE_INFORMATION_EX;
  I
, Drive: Integer;
 
ObjectTypeNumber: Byte;
 
FileDirectory, FilePath, ProcessName: String;
 
SystemInformation, TempSI: PSYSTEM_PROCESS_INFORMATION;
 
DosDevices: array [0..25] of DriveQueryData;
 
LongFileName, TmpFileName: String;
begin
 
SetLength(LongFileName, MAX_PATH);
 
GetLongPathNameA(PChar(FileName), @LongFileName[1], MAX_PATH);
 
 
for Drive := 0 to 25 do
 
begin
   
DosDevices[Drive].DiskLabel := Chr(Drive + Ord('a')) + ':';
   
SetLength(DosDevices[Drive].DiskDosQuery, MAXCHAR);
   
ZeroMemory(@DosDevices[Drive].DiskDosQuery[1], MAXCHAR);
   
QueryDosDevice(PChar(DosDevices[Drive].DiskLabel),
     
@DosDevices[Drive].DiskDosQuery[1], MAXCHAR);
   
DosDevices[Drive].DosQueryLen := Length(PChar(DosDevices[Drive].DiskDosQuery));
   
SetLength(DosDevices[Drive].DiskDosQuery, DosDevices[Drive].DosQueryLen);
 
end;
 
 
ObjectTypeNumber := 0;
 
SetDebugPriv;
  hFile
:= CreateFile('NUL', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);
 
if hFile = INVALID_HANDLE_VALUE then RaiseLastOSError;
 
try
    pHandleInfo
:= GetInfoTable(SystemHandleInformation);
   
if pHandleInfo = nil then RaiseLastOSError;
   
try
     
for I := 0 to pHandleInfo^.NumberOfHandles - 1 do
       
if pHandleInfo^.Information[I].Handle = hFile then
         
if pHandleInfo^.Information[I].ProcessId = GetCurrentProcessId then
         
begin
           
ObjectTypeNumber := pHandleInfo^.Information[I].ObjectTypeNumber;
           
Break;
         
end;
   
finally
     
FreeMem(pHandleInfo);
   
end;
 
finally
   
CloseHandle(hFile);
 
end;
 
 
SystemInformation := GetInfoTable(SystemProcessesAndThreadsInformation);
 
if SystemInformation <> nil then
 
try
    pHandleInfo
:= GetInfoTable(SystemHandleInformation);
   
if pHandleInfo <> nil then
   
try
      ProgressBar1
.Position := 0;
      ProgressBar1
.Max := pHandleInfo^.NumberOfHandles;
     
for I := 0 to pHandleInfo^.NumberOfHandles - 1 do
     
begin
       
if pHandleInfo^.Information[I].ObjectTypeNumber = ObjectTypeNumber then
       
begin
          hProcess
:= OpenProcess(PROCESS_DUP_HANDLE, True,
            pHandleInfo
^.Information[I].ProcessId);
         
if hProcess > 0 then
         
try
           
if DuplicateHandle(hProcess, pHandleInfo^.Information[I].Handle,
             
GetCurrentProcess, @hFile, 0, False, DUPLICATE_SAME_ACCESS) then
           
try
             
if Application.Terminated then Exit;
 
             
FilePath := GetFileNameFromHandle(hFile);
             
if FilePath <> '' then
             
begin
               
FileDirectory := '';
               
for Drive := 0 to 25 do
                 
if DosDevices[Drive].DosQueryLen > 0 then
                   
if Copy(FilePath, 1, DosDevices[Drive].DosQueryLen) =
                     
DosDevices[Drive].DiskDosQuery then
                   
begin
                     
FileDirectory := DosDevices[Drive].DiskLabel;
                     
Delete(FilePath, 1, DosDevices[Drive].DosQueryLen);
                     
Break;
                   
end;
 
               
if FileDirectory = '' then Continue;    
 
               
TempSI := SystemInformation;
                repeat
                 
if TempSI^.ProcessID =
                    pHandleInfo
^.Information[I].ProcessId then
                 
begin
                   
ProcessName := TempSI^.ModuleName;
                   
Break;
                 
end;
                 
TempSI := Pointer(DWORD(TempSI) + TempSI^.NextOffset);
               
until TempSI^.NextOffset = 0;
 
               
SetLength(TmpFileName, MAX_PATH);
               
GetLongPathNameA(PChar(FileDirectory + FilePath), @TmpFileName[1], MAX_PATH);
                Memo1
.Lines.Add(ProcessName + ': ' + TmpFileName);  
             
end;
           
finally
             
CloseHandle(hFile);
           
end;
         
finally
           
CloseHandle(hProcess);
         
end;
       
end;
        ProgressBar1
.Position := ProgressBar1.Position + 1;
       
Application.ProcessMessages;
     
end;
   
finally
     
FreeMem(pHandleInfo);
   
end;
 
finally
   
FreeMem(SystemInformation);
 
end;
 
ShowMessage('All handles found.');
end;
 
end.

Взято из https://forum.sources.ru

Автор: Rouse_