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

Вниз

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 вся ветка

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

Наверх




Память: 0.53 MB
Время: 0.047 c
2-1181845802
Infinityx93
2007-06-14 22:30
2007.07.08
как чистить стринггрид???


1-1178705716
logslava
2007-05-09 14:15
2007.07.08
Зависание программы при выходе из метода моего класса


15-1180880346
Германн
2007-06-03 18:19
2007.07.08
Какая хорошая штука - Медовуха!


11-1164572053
Psychedelic
2006-11-26 23:14
2007.07.08
Предложение для всех.


15-1181487812
@!!ex_
2007-06-10 19:03
2007.07.08
Google Earth





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский