FS Filter Driver
От: __Dee0  
Дата: 25.12.07 08:19
Оценка:
Доброго времени суток, коллеги...

Возникла небольшая проблема.. Пишу драйвер-фильтр файловой системы, который помимо остальных функций должен "уметь" прятать файлы (эдакий "карантин").

Когда получаю 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;
    }


Подскажите решение...
Re: FS Filter Driver
От: ABar Украина  
Дата: 25.12.07 08:41
Оценка:
Здравствуйте, __Dee0, Вы писали:

__D>Доброго времени суток, коллеги...


__D>Возникла небольшая проблема.. Пишу драйвер-фильтр файловой системы, который помимо остальных функций должен "уметь" прятать файлы (эдакий "карантин").


__D>Когда получаю IRP с флагом SL_RETURN_SINGLE_ENTRY, обнуляю структуру соответствующего размера по указателю Irp->UserBuffer. Очевидно, что файл все равно отображается (без имени, атрибутов и пр.).

__D>Подскажите решение...

В такой ситуации нужно сформировать IRP с запросом IRP_MJ_DIRECTORY_CONTROL/IRP_MN_QUERY_DIRECTORY, указать там RestartScan=FALSE, ReturnSingleEntry=TRUE. Когда данные вернуться, скопировать их в исходный буффер или вернуть STATUS_NO_MORE_FILES, если других файлов нет.
Re[2]: FS Filter Driver
От: __Dee0  
Дата: 25.12.07 08:58
Оценка:
Здравствуйте, ABar, Вы писали:

AB>В такой ситуации нужно сформировать IRP с запросом IRP_MJ_DIRECTORY_CONTROL/IRP_MN_QUERY_DIRECTORY, указать там RestartScan=FALSE, ReturnSingleEntry=TRUE. Когда данные вернуться, скопировать их в исходный буффер или вернуть STATUS_NO_MORE_FILES, если других файлов нет.


Неужели нет вариантов попроще?
Re[2]: FS Filter Driver
От: __Dee0  
Дата: 25.12.07 09:50
Оценка:
Я не могу просто так вернуть статус STATUS_NO_SUCH_FILE из completion routine..
В completion routine нужно вернуть STATUS_MORE_PROCESSING_REQUIRED и в dispatch routine дождаться пока все layered drivers обработают IRP.
И только после этого изменить статус на STATUS_NO_SUCH_FILE и вызвать IoCompleteRequest.


Все это замечательно и весь код обработки должен быть перенесен в dispatch routine.
Поправьте, если я ошибаюсь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.