Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.04;
Скачать: CL | DM;

Вниз

Получить список открытых в системе файлов (WinNT)   Найти похожие ветки 

 
Anatolii   (2006-09-18 11:05) [0]

Достаточно долго возился с поиском информации по теме. Информации мало :( Нижеприведенный пример не работает... Список дисков получает корректно, а вот уже при запросе имен файлов, DeviceIoControl возвращает в buf пустые значения. Может ошибка в коде, может для NT систем можно иначе получить список файлов?

procedure TForm1.Button1Click(Sender: TObject);
type
 TRegs = Record
   reg_EBX   : Dword;
   reg_EDX   : Pointer;//PChar;
   reg_ECX   : Dword;
   reg_EAX   : Dword;
   reg_EDI   : Dword;
   reg_ESI   : Dword;
   reg_Flags : Dword;
 end;
var nd,j,i:integer;
 buf: array[0..100] of char;
 F,cb:Cardinal;
 Regs:TRegs;
begin
  nd := 0;

  j := GetLogicalDriveStrings(MAX_PATH,@buf);
  for i := 1 to j do if buf[i]=":" then Inc(nd);

  F := CreateFile(PChar("\\.\vwin32"),0,0,NIL,0,FILE_FLAG_DELETE_ON_CLOSE,0);

  for i := 3 to nd do      //Пропускаем диски A и B
  begin
   j := 0;
   while True do
   begin
    FillChar(Regs,SizeOf(TRegs),0);
    FillChar(buf,SizeOf(TRegs),0);
    Regs.reg_EBX := i;
    Regs.reg_EDX := @buf;
    Regs.reg_ECX := $486D;
    Regs.reg_EAX := $440D;
    Regs.reg_EDI := 0;
    Regs.reg_ESI := j;
    Inc(j);
    DeviceIoControl(F,1,@Regs,sizeof(Regs),@Regs,sizeof(regs),cb,NIL);
    OemToChar(@buf,@buf);
    ListBox2.Items.Add(StrPas(@buf));
    if (Regs.reg_Flags or 1 = Regs.reg_Flags) then break;
   end;
  end;
  CloseHandle(F);
end;


 
Rouse_ ©   (2006-09-18 12:16) [1]

Вот так:

////////////////////////////////////////////////////////////////////////////////
//
//  ****************************************************************************
//  * 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;


 
Rouse_ ©   (2006-09-18 12:17) [2]

 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;


 
Rouse_ ©   (2006-09-18 12:17) [3]

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.


 
Anatolii   (2006-09-18 14:43) [4]

100% попадание. Спасибо большое :)


 
Rouse_ ©   (2006-09-18 15:08) [5]

Ты только учитывай что не все файлы можно так получить ибо не всегда OpenProcess отработает с флагом PROCESS_DUP_HANDLE, особливо касается фалов открытых из драйвера...


 
BiN ©   (2006-09-21 10:42) [6]


> Rouse_ ©   (18.09.06 12:17) [2]
>...
> WAIT_TIMEOUT:
        TerminateThread(hThread, 0);


Я понимаю, что зависает, но ведь по живому режешь...
-)

зыж
как вариант можно попробовать поиграть с GetMappedFileName.


 
Rouse_ ©   (2006-09-21 11:45) [7]


> Я понимаю, что зависает, но ведь по живому режешь...

А что делать, на синхронном пайпе висить, шоб его приподняло :) Приходиться делать подобным образом, потомучто другие методы не дали результата :)


 
Rouse_ ©   (2006-09-21 11:47) [8]

Но вообще на практике это обходиться NtQueryInformationFile которая за пайп даже не хватается и посему реально TerminateThread не отрабатывается, а осталось со времени экспериментов :)



Страницы: 1 вся ветка

Текущий архив: 2007.02.04;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.03 c
15-1169046406
Pasha L
2007-01-17 18:06
2007.02.04
Простой вопрос: как поставить компонент


15-1168590355
Empleado
2007-01-12 11:25
2007.02.04
Календарь менять будем? Аль так оставим?


2-1168772080
Garacio
2007-01-14 13:54
2007.02.04
в ListView правильно SubItems.add или SubItems.Strings


2-1168868626
Галинка
2007-01-15 16:43
2007.02.04
Как вытащить структуру датасета из XML


2-1168937219
Cara
2007-01-16 11:46
2007.02.04
Проверка пароля.