Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

NtQueryDirectoryFile [D7, WinXP]


Страницы:   1 2

SysError ©   (2007-01-18 22:41:00) 

Напишите пожалуйста, как получить ПОЛНЫЙпуть к файлу или катологу с помощью функции 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 получаю название файлов без путей :-(


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


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

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


SysError   (2007-01-30 18:49:00) [2]

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

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

Вот она

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


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


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


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


BiN   (2007-01-23 23:34:00) [4]


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

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


SysError   (2007-01-23 22:36:00) [5]

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


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


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

GetLogicalDriveStrings, QueryDosDevice


SysError   (2007-01-22 22:54:00) [7]

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

Только пару вопросов(??)
Как определить букву диска по пути?
Получить путь файла без *мусора*?
Как я понял нужно опредилить все по порядку диски в системе и пронумеровать,
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-е вхождени символа '\'.может так лучше.
Или существуют более простые, быстрые и надежные способы разрешить мои вопросы???


SysError   (2007-01-22 19:25:00) [8]

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


Riply   (2007-01-22 16:47:00) [9]

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


BiN   (2007-01-22 15:32:00) [10]


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


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


Riply   (2007-01-22 15:14:00) [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 10:55:00) [12]


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

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


Riply   (2007-01-22 10:46:00) [13]

> [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 09:58:00) [14]


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

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


Riply   (2007-01-22 09:46:00) [15]

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


Riply   (2007-01-22 08:54:00) [16]

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


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

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

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


SysError   (2007-01-20 16:08:00) [18]

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


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

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-19 18:06:00) [20]

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

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;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо