Доброго времени суток, коллеги...
Возникла небольшая проблема.. Пишу драйвер-фильтр файловой системы, который помимо остальных функций должен "уметь" прятать файлы (эдакий "карантин").
Когда получаю IRP с флагом SL_RETURN_SINGLE_ENTRY, обнуляю структуру соответствующего размера по указателю Irp->UserBuffer. Очевидно, что файл все равно отображается (без имени, атрибутов и пр.).
Обработка происходит в completion routine.
Собственно сама completion routine:
NTSTATUS
OurFilterHookDone(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
BOOLEAN bThrowNext = TRUE;
CRHFileSystemDriver* pFSD = (CRHFileSystemDriver*) Context;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
//LPHOOK_EXTENSION hookExt = (LPHOOK_EXTENSION)DeviceObject->DeviceExtension;
//PFILE_OBJECT FileObject = IrpSp->FileObject;
if( IrpSp->MajorFunction == IRP_MJ_DIRECTORY_CONTROL &&
IrpSp->MinorFunction == IRP_MN_QUERY_DIRECTORY &&
KeGetCurrentIrql() == PASSIVE_LEVEL)
{
PQUERY_DIRECTORY pQueryDirectory = (PQUERY_DIRECTORY)&IrpSp->Parameters;
PVOID FileInformationBuffer = Irp->UserBuffer;
PVOID volatile p = Irp->UserBuffer;
PVOID volatile pLast = NULL;
ULONG FileInformationBufferLength = Irp->IoStatus.Information;
FILE_INFORMATION_CLASS FileInfoClass = pQueryDirectory->FileInformationClass;
DebugPrint("FileInfoClass: %x\n", FileInfoClass);
if (FileInfoClass == FileDirectoryInformation ||
FileInfoClass == FileFullDirectoryInformation ||
FileInfoClass == FileIdFullDirectoryInformation ||
FileInfoClass == FileBothDirectoryInformation ||
FileInfoClass == FileIdBothDirectoryInformation ||
FileInfoClass == FileNamesInformation )
{
ULONG nTotalSize = (ULONG)Irp->IoStatus.Information;
BOOLEAN bReset = FALSE;
ULONG nIteration = 0;
if(FileInformationBufferLength > 0)
{
BOOLEAN bDone = FALSE;
do
{
//CHAR* pszFullPathName;
//GETPATHNAME(FALSE);
WCHAR* pwszFileName = (WCHAR*)GetDirEntryFileName(p, FileInfoClass);
DebugPrint("Filename: %ws\n", pwszFileName);
// Check to see if there is a link to another file or if this is the last file
//bDone = !GetDirEntryLinkToNext(p, FileInfoClass);
if (pFSD->IsHiddenFile(pwszFileName) || pFSD->IsHiddenDirectory(pwszFileName))
{
DebugPrint("Hiding file or directory.\n");
if(nIteration == 0)
{
if ((IrpSp->Flags == SL_RETURN_SINGLE_ENTRY) || ((GetDirEntryLinkToNext(p, FileInfoClass) ) == 0))
{
RtlZeroMemory(p, GetDirEntrySize(p, FileInfoClass));
nTotalSize = 0;
Irp->IoStatus.Status = STATUS_NO_SUCH_FILE;
bThrowNext = FALSE;
}
else
{
ULONG NextEntryOffset = (GetDirEntryLinkToNext(p, FileInfoClass) );
PVOID pTemp = ExAllocatePool(PagedPool, nTotalSize);
if (pTemp != NULL)
{
nTotalSize -= NextEntryOffset;
RtlCopyMemory(pTemp, ((PBYTE)p + NextEntryOffset), nTotalSize);
RtlZeroMemory(p, nTotalSize + NextEntryOffset);
RtlCopyMemory(p, pTemp, nTotalSize);
ExFreePool(pTemp);
}
bReset = TRUE;
}
}
else if ((nIteration > 0) && ((GetDirEntryLinkToNext(p, FileInfoClass) ) != 0))
{
ULONG NextEntryOffset = (GetDirEntryLinkToNext(p, FileInfoClass) );
ULONG nSize = ((PBYTE) FileInformationBuffer + FileInformationBufferLength) -\
(PBYTE)p - NextEntryOffset;
PVOID pTemp = ExAllocatePool(PagedPool, nSize);
if (pTemp != NULL)
{
nTotalSize -= NextEntryOffset;
RtlCopyMemory(pTemp, ((PBYTE)p + NextEntryOffset), nSize);
RtlZeroMemory(p, nSize + NextEntryOffset);
RtlCopyMemory(p, pTemp, nSize);
ExFreePool(pTemp);
}
bReset = TRUE;
}
else if ((nIteration > 0) && (GetDirEntryLinkToNext(p, FileInfoClass) == 0))
{
ULONG nSize = ((PBYTE) FileInformationBuffer + FileInformationBufferLength) - (PBYTE) p;
SetDirEntryLinkToNext(/*((PBYTE)p + GetDirEntryLinkToNext(p, FileInfoClass) )*/pLast, FileInfoClass, 0);
RtlZeroMemory(p, nSize);
nTotalSize -= nSize;
// Irp->IoStatus.Status = STATUS_NO_MORE_FILES;
}
}
nIteration++;
if (!bReset)
{
pLast = p;
p = ((PBYTE)p + GetDirEntryLinkToNext(p, FileInfoClass) );
}
else
bReset = FALSE;
} while(p != pLast);
Irp->IoStatus.Information = nTotalSize;
}
}
}
//
// Now we have to mark Irp as pending if necessary
//
if( bThrowNext && Irp->PendingReturned ) {
IoMarkIrpPending( Irp );
}
return Irp->IoStatus.Status;
}
Подскажите решение...
Я не могу просто так вернуть статус STATUS_NO_SUCH_FILE из completion routine..
В completion routine нужно вернуть STATUS_MORE_PROCESSING_REQUIRED и в dispatch routine дождаться пока все layered drivers обработают IRP.
И только после этого изменить статус на STATUS_NO_SUCH_FILE и вызвать IoCompleteRequest.
Все это замечательно и весь код обработки должен быть перенесен в dispatch routine.
Поправьте, если я ошибаюсь.