Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2007.02.04;
Скачать: [xml.tar.bz2];

Вниз

Получить список открытых в системе файлов (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 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.02.04;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.044 c
2-1168999667
DmitrichJ
2007-01-17 05:07
2007.02.04
Ну слишком медленный StringGrid. Что делать?


3-1163160336
Kolan
2006-11-10 15:05
2007.02.04
Как колонки сделать строками(SQL)


1-1165939315
Dmitry_177
2006-12-12 19:01
2007.02.04
Сообщение при нажатии на кнопку "свернуть все окна"


2-1169106953
KyRo
2007-01-18 10:55
2007.02.04
TMediaPlayer


2-1169040951
InfraRed
2007-01-17 16:35
2007.02.04
Функция RegConnectRegistry





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский