Всем доброго! Фильтрую пакеты, все вроде было нормально, пока не обнаружил следующую странность. Открываю файл Far'ом и не получаю полного пути к файлу, а только имя файла, к примеру если открываю тот же файл notepad'ом то все гуд. Как получить полный путь к файлу в данной ситуации? Заранее спасибо!
строка FileName валидна только во время обработки IRP_MJ_CREATE,после создания файла там может быть что угодно.Поэтому для того чтобы узнать имя файла нужно отправить объекту ФС IRP_MJ_QUERY_INFORMATION указав класс FileNameInformation
Значит смотришь не прямыми руками. Код (Text): PUNICODE_STRING FileName; ULONG Len = 0; ULONG Len2 = 0; PWCHAR fName, p; BOOLEAN bFirst = TRUE; if (FileObject->RelatedFileObject) { FileName = &FileObject->RelatedFileObject->FileName; if (FileName->Buffer) { Len = FileName->Length >> 1; memcpy(OutName, FileName->Buffer, FileName->Length); } } if (FileObject->FileName.Buffer) { FileName = &FileObject->FileName; memcpy(&OutName[Len], FileName->Buffer, FileName->Length); Len += FileName->Length >> 1; }
Если это каждый раз делать в обработчике create, то производитетльность пострадает ощутимо. IRP_MJ_QUERY_INFORMATION выполняется довольно долго.
Это делается не каждый раз,т.к. процент "относительных открытий" довольно маленький,зато можно не боятся BSOD'a если на месте буфера строки окажется мусор, как я уже говорил,буфер с именем файла 100% валиден только в процессе обработки IRP_MJ_CREATE
Просмотри сорцов винды показал, что это не так. После посылки IRP_MJ_CLOSE делается освобождение буфера Код (Text): if (fileObject->FileName.Length != 0) { ExFreePool( fileObject->FileName.Buffer ); } Тоесть необходимо просто делать проверку на fileObject->FileName.Length. Если буфер освобождается черт знает где, то почему же винда тогда не падает при закрытии файлов? Вот буфер RelatedFileObject имхо может быть освобожден до закрытия основного FileObject (поправьте меня, если я ошибаюсь).
у тебя есть сорцы NTFS ? Кроме IO manager'a буфер трогают драйверы ФС,в рассылке от OSR товарищами из микрософт ясно об этом сказано.
PE386, спасибо за код, но если честно мне он никак не помог, потому как в IRP_MJ_CREATE, если и присутсвует RelatedFileObject, то буфер RelatedFileObject->FileName.Buffer пуст. Замечу проверку делаю в диспечере, потому как условия таковы, получить полный путь к файлу в диспечере. MiraclE, скорей всего я пойду вашем методом.
MiraclE, да кстати я тут подумал, что IRP_MJ_QUERY_INFORMATION тоже не получиться использовать, проблема в том что прежде чем послать запрос, нужно открыть файл, т.е. получить хэндл или вы знаете иной способ? А если пытаться открыть, то в результате получаем рекурсию или я не прав?
Ни какой рекурсии не будет,и хэндлы никакие не нужны т.к. мы посылаем ирп напрямую объекту устройство ФС.Вот пример такой функции: Код (Text): BOOLEAN QueryFile( PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, FILE_INFORMATION_CLASS FileInformationClass, PVOID FileQueryBuffer, ULONG FileQueryBufferLength ) { PIRP irp; KEVENT event; IO_STATUS_BLOCK IoStatusBlock; PIO_STACK_LOCATION ioStackLocation; NTSTATUS status; // // инициализируем объект событие // KeInitializeEvent(&event, SynchronizationEvent, FALSE); // // создаем ирп // // irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if(!irp) { // // ошибка создания ирп // return FALSE; } // // заполняем тело ирп // irp->AssociatedIrp.SystemBuffer = FileQueryBuffer; irp->UserEvent = &event; irp->UserIosb = &IoStatusBlock; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irp->RequestorMode = KernelMode; irp->Flags = 0; ioStackLocation = IoGetNextIrpStackLocation(irp); ioStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION; ioStackLocation->DeviceObject = DeviceObject; ioStackLocation->FileObject = FileObject; ioStackLocation->Parameters.QueryFile.Length = FileQueryBufferLength; ioStackLocation->Parameters.QueryFile.FileInformationClass = FileInformationClass; // // устанавливаем процедуру завершения // IoSetCompletionRoutine(irp, QueryFileComplete, 0, TRUE, TRUE, TRUE); // // послыаем ирп драйверу фс // status=IoCallDriver(DeviceObject, irp); if(status==STATUS_PENDING){ //если завершение ирп было отложенно ждем на событии KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); status=IoStatusBlock.Status; } // // запрос обработан - возвращаем статус // // return NT_SUCCESS(status); } а вообще можно в ддк поглядеть по вдумчевее и подобные вопросы сами отпадут