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

Вниз

NtQueryDirectoryFile   Найти похожие ветки 

 
SysError ©   (2007-01-18 22:41) [0]

Напишите пожалуйста, как получить ПОЛНЫЙ путь к файлу или катологу с помощью функции NtQueryDirectoryFile.

делаю так...
var
 Name: string;
 FileDirectoryInfo: PFILE_DIRECTORY_INFORMATION;

.....

FileDirectoryInfo := PFILE_DIRECTORY_INFORMATION(pointer(dword(FileInformation) + Offset));
Name := Copy(WideCharToString(FileDirectoryInfo.FileName), 1, FileDirectoryInfo.FileNameLength div 2);
if StrCmp(Name, Root) then //тут сравниваем ==> одинаковый ---> скрываем
.........

В Name получаю название файлов без путей :-(


 
Игорь Шевченко ©   (2007-01-19 10:44) [1]


> делаю так...


мало кода


 
SysError ©   (2007-01-19 18:06) [2]

Делаю перехват, вот обработка...

function myNtQueryDirectoryFile(FileHandle: HWND; Event: HWND;
ApcRoutine: PIO_APC_ROUTINE; ApcContext: PVOID; IoStatusBlock: PIO_STATUS_BLOCK;
FileInformation: PVOID; FileInformationLength: ULONG;
FileInformationClass: FILE_INFORMATION_CLASS; ReturnSingleEntry: ByteBool;
FileName: PUNICODE_STRING; RestartScan: ByteBool): NTSTATUS; stdcall;
var
 Offset: dword;
 Name: string;
 LastFileDirectoryInfo, FileDirectoryInfo: PFILE_DIRECTORY_INFORMATION;
 LastFileFullDirectoryInfo, FileFullDirectoryInfo: PFILE_FULL_DIRECTORY_INFORMATION;
 LastFileBothDirectoryInfo, FileBothDirectoryInfo: PFILE_BOTH_DIRECTORY_INFORMATION;
 LastFileNamesInfo, FileNamesInfo: PFILE_NAMES_INFORMATION;
begin
 Result := NtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext,IoStatusBlock, FileInformation, FileInformationLength, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);
 if Result <> 0 then Exit;
 Offset := 0;
 case dword(FileInformationClass) of
   1:
     begin
       FileDirectoryInfo := nil;
       repeat
         LastFileDirectoryInfo := FileDirectoryInfo;
         FileDirectoryInfo := PFILE_DIRECTORY_INFORMATION(pointer(dword(FileInformation) + Offset));
         Name := Copy(WideCharToString(FileDirectoryInfo.FileName), 1, FileDirectoryInfo.FileNameLength div 2);
         if StrCmp(Name, Root) then
         begin
           if FileDirectoryInfo.NextEntryOffset = 0 then
           begin
             if LastFileDirectoryInfo <> nil then LastFileDirectoryInfo.NextEntryOffset := 0
             else Result := NTSTATUS($C000000F);
             Exit;
           end
           else
           begin
             LastFileDirectoryInfo.NextEntryOffset := LastFileDirectoryInfo.NextEntryOffset + FileDirectoryInfo.NextEntryOffset;
           end;
         end;
         Offset := Offset + FileDirectoryInfo.NextEntryOffset;
       until FileDirectoryInfo.NextEntryOffset = 0;
     end;
   2:
     begin
       FileFullDirectoryInfo := nil;
       repeat
         LastFileFullDirectoryInfo := FileFullDirectoryInfo;
         FileFullDirectoryInfo := PFILE_FULL_DIRECTORY_INFORMATION(pointer(dword(FileInformation) + Offset));
         Name := Copy(WideCharToString(FileFullDirectoryInfo.FileName), 1, FileFullDirectoryInfo.FileNameLength div 2);
         if StrCmp(Name, Root) then
         begin
           if FileFullDirectoryInfo.NextEntryOffset = 0 then
           begin
             if LastFileFullDirectoryInfo <> nil then LastFileFullDirectoryInfo.NextEntryOffset := 0
             else Result := NTSTATUS($C000000F);
             Exit;
           end
           else
           begin
             LastFileFullDirectoryInfo.NextEntryOffset := LastFileFullDirectoryInfo.NextEntryOffset + FileFullDirectoryInfo.NextEntryOffset;
           end;
         end;
         Offset := Offset + FileFullDirectoryInfo.NextEntryOffset;
       until FileFullDirectoryInfo.NextEntryOffset = 0;
     end;
   3:
     begin
       FileBothDirectoryInfo := nil;
       repeat
         LastFileBothDirectoryInfo := FileBothDirectoryInfo;
         FileBothDirectoryInfo := PFILE_BOTH_DIRECTORY_INFORMATION(pointer(dword(FileInformation) + Offset));
         Name := Copy(WideCharToString(FileFullDirectoryInfo.FileName), 1, FileFullDirectoryInfo.FileNameLength div 2);
         if StrCmp(Name, Root) then
         begin
           if FileBothDirectoryInfo.NextEntryOffset = 0 then
           begin
             if LastFileBothDirectoryInfo <> nil then LastFileBothDirectoryInfo.NextEntryOffset := 0
             else Result := NTSTATUS($C000000F);
             Exit;
           end
           else
           begin
             LastFileBothDirectoryInfo.NextEntryOffset := LastFileBothDirectoryInfo.NextEntryOffset + FileBothDirectoryInfo.NextEntryOffset;
           end;
         end;
         Offset := Offset + FileBothDirectoryInfo.NextEntryOffset;
       until FileBothDirectoryInfo.NextEntryOffset = 0;
     end;
   12:
     begin
       FileNamesInfo := nil;
       repeat
         LastFileNamesInfo := FileNamesInfo;
         FileNamesInfo := PFILE_NAMES_INFORMATION(pointer(dword(FileInformation) + Offset));
         Name := Copy(WideCharToString(FileNamesInfo.FileName), 1, FileNamesInfo.FileNameLength div 2);
         if StrCmp(Name, Root) then
         begin
           if FileNamesInfo.NextEntryOffset = 0 then
           begin
             if LastFileNamesInfo <> nil then LastFileNamesInfo.NextEntryOffset := 0
             else Result := NTSTATUS($C000000F); //STATUS_NO_SUCH_FILE
             Exit;
           end
           else
           begin
             LastFileNamesInfo.NextEntryOffset := LastFileNamesInfo.NextEntryOffset + FileNamesInfo.NextEntryOffset;
           end;
         end;
         Offset := Offset + FileNamesInfo.NextEntryOffset;
       until FileNamesInfo.NextEntryOffset = 0;
     end;
 end;
end;


 
SysError ©   (2007-01-19 18:56) [3]

Sorry...  с ошибкой

Там где
case dword(FileInformationClass) of

3 :
..........................
Name := Copy(WideCharToString(FileBothDirectoryInfo.FileName), 1, FileBothDirectoryInfo.FileNameLength div 2);
............................

Результа все теже имена файлов...
Пример
.
..
Ring0.pas
NtDll.pas
NtPEB.pas
HsNtDef.pas
NTSTATUSDEFS.PAS
NtUtils.pas
advApiHook.pas
afxCodeHook.pas

Может надо еще использовать FileHandle: HWND ???


 
SysError ©   (2007-01-20 16:08) [4]

Неужели никто не знает. Пожалуйста, откликнитесь на мою просьбу.


 
BiN   (2007-01-21 23:08) [5]

> SysError ©   (18.01.07 22:41)  
>
> Напишите пожалуйста, как получить ПОЛНЫЙ путь к файлу или
> катологу с помощью функции NtQueryDirectoryFile.

С помощью NtQueryDirectoryFile никак.
Используй NtQueryObject(FileHandle, ObjectNameInformation...


 
Riply ©   (2007-01-22 08:54) [6]

>[5] BiN (21.01.07 23:08)
>С помощью NtQueryDirectoryFile никак.
>Используй NtQueryObject(FileHandle, ObjectNameInformation...
Мне казалось, что в этой ситуации ("Делаю перехват, вот обработка..."),
использование NtQueryObject "напрямую" (с параметром FileHandle)
не всегда даст корректный результат.
Например, когда "жертва перехвата" многократно вызывает NtQueryDirectoryFile
с RestartScan равным True.


 
Riply ©   (2007-01-22 09:46) [7]

Извините - ошиблась :(
>с RestartScan равным True.
Разумеется "с RestartScan равным False".


 
BiN ©   (2007-01-22 09:58) [8]


> Riply ©   (22.01.07 08:54) [6]
>
> Мне казалось, что в этой ситуации ("Делаю перехват, вот
> обработка..."),
> использование NtQueryObject "напрямую" (с параметром FileHandle)
> не всегда даст корректный результат.
> Например, когда "жертва перехвата" многократно вызывает
> NtQueryDirectoryFile
> с RestartScan равным True.

FileHandle в данном случае - это описатель директории. Не понимаю, какая в данном случае есть зависимость между значением параметра RestartScan и результатом функции NtQueryObject.


 
Riply ©   (2007-01-22 10:46) [9]

> [8] BiN ©   (22.01.07 09:58)
> Не понимаю, какая в данном случае есть зависимость между
>значением параметра RestartScan и результатом функции NtQueryObject.
var
FHandle: THandle;
begin
// Получаем первый хандл
RestartScan := True;
repeat
 Result := NtQueryDirectoryFile(FHandle, ..., RestartScan);
 if Result = STATUS_SUCCESS then
  begin
   // Здесь, как мне кажется, NtQueryObject(FHandle, ...)
   // будет возвращать имя файла/директории для которой
   // FHandle был получен первый раз, а не для новой,
   // тем более не для вложенной
   RestartScan := False;
  end;
until Result <> STATUS_SUCCESS;

У меня сейчас нет возможности это проверить :(
Проверю примерно через час.
P.S. Очень возможно, что я ошибаюсь :)


 
BiN ©   (2007-01-22 10:55) [10]


> Riply ©   (22.01.07 10:46) [9]

NtQueryDirectoryFile используется для получения информации о содержимом одной директории. Вложенный директории при этом не сканируются.


 
Riply ©   (2007-01-22 15:14) [11]

>BiN ©   (22.01.07 10:55)
>NtQueryDirectoryFile используется для получения информации о содержимом одной директории.
Да, я ошиблась, сказав про вложенные директории. :(( Приношу извинения.
Но с перечислением при RestartScan равным False, вроде - нет. :)
Проверяю так :
function GetDirectoryItemNames(var FHandle: THandle; List: TStrings): NTSTATUS;
const
BufferSize = $4000;
var
Buffer: Pointer;
ObjName: string;
aStatus: NTSTATUS;
RestartScan: Boolean;
IoStBlock: TIoStatusBlock;
begin
Result := ERROR_OUTOFMEMORY;
GetMem(Buffer, BufferSize);
if not Assigned(Buffer) then Exit;
try
 RestartScan := True;
 repeat
  Result := NtQueryDirectoryFile(FHandle, 0, nil, nil, @IoStBlock,
                                 Buffer, BufferSize, Ord(FileDirectoryInformation),
                                 True, nil, RestartScan);
  if Result = STATUS_SUCCESS then
   begin
    ObjName := "";
    aStatus := QueryObjectNameEx_(FHandle, ObjName);// получаем имя объекта (NtQueryObject)
    if aStatus <> STATUS_SUCCESS then ObjName := NtErrorString(aStatus);
    Str_ResetLength(ObjName);
    with PFILE_DIRECTORY_INFORMATION(Buffer)^ do
     List.Add(WideCharLenToString(FileName, FileNameLength div SizeOf(WideChar)) + " = " + ObjName);
    RestartScan := False;
   end;
 until Result <> STATUS_SUCCESS;
finally
 FreeMem(Buffer);
end;
end;

Возвращаемый список :
Books = \Device\HarddiskVolume2\
Buffer = \Device\HarddiskVolume2\
Delete Files = \Device\HarddiskVolume2\
Delphi Source = \Device\HarddiskVolume2\
Help = \Device\HarddiskVolume2\
Images = \Device\HarddiskVolume2\
Internet = \Device\HarddiskVolume2\
Journals = \Device\HarddiskVolume2\
RECYCLER = \Device\HarddiskVolume2\
Rescue = \Device\HarddiskVolume2\
Riply = \Device\HarddiskVolume2\
Setup = \Device\HarddiskVolume2\
System Volume Information = \Device\HarddiskVolume2\
Temp = \Device\HarddiskVolume2\
TestDir = \Device\HarddiskVolume2\  
Tools = \Device\HarddiskVolume2\


 
BiN ©   (2007-01-22 15:32) [12]


> Riply ©   (22.01.07 15:14) [11]
>
> Возвращаемый список :
> Books = \Device\HarddiskVolume2\
> ...


Всё правильно. Полный путь и будет равен \Device\HarddiskVolume2\Books


 
Riply ©   (2007-01-22 16:47) [13]

>Всё правильно. Полный путь и будет равен \Device\HarddiskVolume2\Books
Да. Что-то я переаботала.
Уткнулась в то, что при "рескане" NtQueryObject будет выдавать
одну и ту же директорию и все тут :))
А добавить FileName к ней оказалось ну слишком сложно :))


 
SysError ©   (2007-01-22 19:25) [14]

Больщое спосибо всем откликнулся, буду пробывать!!!


 
SysError ©   (2007-01-22 22:54) [15]

Ура, заработала.  ;-)={-<

Только пару вопросов(??)
Как определить букву диска по пути?
Получить путь файла без *мусора*?
Как я понял нужно опредилить все по порядку диски в системе и пронумеровать,
A=0
C=1
D=2
E=3
F=4 и т.д.

далее разбираем строку
\Device\HarddiskVolume1\Documents and Settings\Рабочий стол\FlashGet.lnk

т.е. HarddiskVolume1 будет равен диску C:\
HarddiskVolume2 = D:\
далее ищем первое вхождение подстроки HarddiskVolume,
вырезаем + еще 2 символа, но если дисков будет больше, к примеру
10 тогда облом... Или искать 3-е вхождени символа "\".может так лучше.
Или существуют более простые, быстрые и надежные способы разрешить мои вопросы???


 
BiN   (2007-01-22 23:57) [16]


> SysError ©   (22.01.07 22:54) [15]
>
> Как определить букву диска по пути?

GetLogicalDriveStrings, QueryDosDevice


 
SysError ©   (2007-01-23 22:36) [17]

Как я понял эти функции GetLogicalDriveStrings, QueryDosDevice совершают обратное (возможно я и ошибаюсь)
т.е. переводят имя диска в путь
пробывал так
i := QueryDosDevice(PChar("X:"), buf, SizeOf(buf));
buf вернул
C:   \Device\HarddiskVolume1
D:   \Device\HarddiskVolume2
E:   \Device\HarddiskVolume3
Следовательно надо это сравнивать с результатом NtQueryObject
и делать вывод на каком мы диске..?..
Что то мне подсказывает что это неплохо замедлит систему..
Нарыл вот такую функцию RtlVolumeDeviceToDosName по описанию
она и переводит *путь* в имя диска, но параметров не нашел.
Подскажите как лучше решить эту проблему.


 
BiN   (2007-01-23 23:34) [18]


> SysError ©   (23.01.07 22:36) [17]

В пользовательском режиме более оптимального способа не знаю (вариант с перечислением символьных ссылок объектной директории \?? как раз реализован в QueryDosDevice).


 
Игорь Шевченко ©   (2007-01-24 12:16) [19]


> Как определить букву диска по пути?


http://www.schevchenko.net.ru/SRC/DeviceIoControl_60.zip
ищи HSDeviceTranslation.pas


 
SysError ©   (2007-01-30 18:49) [20]

Все таки этот, на мой взгляд, не совсем красивый способ с перебором и сравнением не дает мне жить...

После продолжительных поисков удалось нарыть вот эту функцию,
она и занимаеться переводом *путь*в привычный мне вид.
Но вот как ее подогнать под мой код увы не знаю, приложение падает дойдя до этой функции.

Вот она

// Documented in the DDK.
function  RtlVolumeDeviceToDosName(
   VolumeDeviceObject : PVOID;
   DosName : PUNICODE_STRING
 ): NTSTATUS; stdcall; {$IFNDEF RTDL}external ntdll;{$ENDIF}

Вот мой код, уверен что не правильно работаю с UniCode,
раньше не приходилось с ним работать.
Не пинайте сильно, очень хочу разобраться, но своими силами
не получаеться...

 //***************************************
 ObjectInfo : Pointer;
 aStatus : NTSTATUS;

 uniDosName : PUNICODE_STRING;
 dwReturn: DWORD;

begin
 Result := NtQueryDirectoryFileNextHook(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, FileInformationLength, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);
 if Result <> 0 then Exit;
 Offset := 0;

   GetMem(ObjectInfo, sizeOf(OBJECT_INFORMATION_CLASS));
   GetMem(uniDosName, MAX_PATH+1);
   try
   aStatus := NtQueryObject(FileHandle, ObjectNameInformation, ObjectInfo, MAX_PATH * 2, @dwReturn );
   if Result = STATUS_SUCCESS then
   with POBJECT_NAME_INFORMATION(ObjectInfo)^ do
   RtlVolumeDeviceToDosName(@Name.Buffer,@uniDosName);

   NameDir := WideCharLenToString(uniDosName.Buffer, uniDosName.Length div SizeOf(WideChar));
   
   finally
   FreeMemory(uniDosName.Buffer);
   FreeMem(ObjectInfo);
   end;
 
//===================================


 
BiN ©   (2007-01-30 21:50) [21]


> она и занимаеться переводом *путь*в привычный мне вид.

С какого перепугу? RtlVolumeDeviceToDosName получает в качестве первого параметра указатель на структуру DEVICE_OBJECT. Функция эта может быть вызвана только в режиме ядра.



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

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

Наверх




Память: 0.55 MB
Время: 0.022 c
2-1181835250
Bullfrog
2007-06-14 19:34
2007.07.08
edit


15-1181115561
boriskb
2007-06-06 11:39
2007.07.08
переехать в Казахстан?


1-1178560118
TStas
2007-05-07 21:48
2007.07.08
Какое сообщение надо послать окну, чтобы оно развернулось?


2-1181665056
hahol
2007-06-12 20:17
2007.07.08
иконки


2-1181655463
Riply
2007-06-12 17:37
2007.07.08
Анализ Boot-сектора флоппика.