Форум: "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.039 c