diff --git a/reactos/ntoskrnl/fsrtl/filtrctx.c b/reactos/ntoskrnl/fsrtl/filtrctx.c index 15bff1c2637..55781b6194d 100644 --- a/reactos/ntoskrnl/fsrtl/filtrctx.c +++ b/reactos/ntoskrnl/fsrtl/filtrctx.c @@ -20,9 +20,26 @@ typedef struct _FILE_OBJECT_FILTER_CONTEXTS LIST_ENTRY FilterContexts; } FILE_OBJECT_FILTER_CONTEXTS, *PFILE_OBJECT_FILTER_CONTEXTS; +/* + * @implemented + */ VOID +NTAPI FsRtlPTeardownPerFileObjectContexts(IN PFILE_OBJECT FileObject) { + PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; + + ASSERT(FileObject); + + if (!(FOContext = IoGetFileObjectFilterContext(FileObject))) + { + return; + } + + ASSERT(IoChangeFileObjectFilterContext(FileObject, FOContext, FALSE) == STATUS_SUCCESS); + ASSERT(IsListEmpty(&(FOContext->FilterContexts))); + + ExFreePoolWithTag(FOContext, 'FOCX'); } @@ -50,7 +67,7 @@ FsRtlIsPagingFile(IN PFILE_OBJECT FileObject) } /* - * @unimplemented + * @implemented */ PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI @@ -58,8 +75,47 @@ FsRtlLookupPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + PLIST_ENTRY NextEntry; + PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; + PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL; + + if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject))) + { + return NULL; + } + + ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); + + /* If list is empty, no need to browse it */ + if (!IsListEmpty(&(FOContext->FilterContexts))) + { + for (NextEntry = FOContext->FilterContexts.Flink; + NextEntry != &(FOContext->FilterContexts); + NextEntry = NextEntry->Flink) + { + /* If we don't have any criteria for search, first entry will be enough */ + if (!OwnerId && !InstanceId) + { + PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry; + break; + } + /* Else, we've to find something that matches with the parameters. */ + else + { + TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links); + if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) || + (OwnerId && TmpPerFOContext->OwnerId == OwnerId)) + { + PerFOContext = TmpPerFOContext; + break; + } + } + } + } + + ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); + + return PerFOContext; } /* @@ -105,21 +161,62 @@ FsRtlLookupPerStreamContextInternal(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, } } } + ExReleaseFastMutex(AdvFcbHeader->FastMutex); return PerStreamContext; } /* - * @unimplemented + * @implemented */ NTSTATUS NTAPI FsRtlInsertPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PFSRTL_PER_FILEOBJECT_CONTEXT Ptr) { - KeBugCheck(FILE_SYSTEM); - return STATUS_NOT_IMPLEMENTED; + PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; + + if (!FileObject) + { + return STATUS_INVALID_PARAMETER; + } + + if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + FOContext = IoGetFileObjectFilterContext(FileObject); + if (!FOContext) + { + FOContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJECT_FILTER_CONTEXTS), 'FOCX'); + if (!FOContext) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + ExInitializeFastMutex(&(FOContext->FilterContextsMutex)); + InitializeListHead(&(FOContext->FilterContexts)); + + if (!IoChangeFileObjectFilterContext(FileObject, FOContext, TRUE)) + { + ExFreePoolWithTag(FOContext, 'FOCX'); + + FOContext = IoGetFileObjectFilterContext(FileObject); + if (!FOContext) + { + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + } + } + + ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); + InsertHeadList(&(FOContext->FilterContexts), &(Ptr->Links)); + ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); + + return STATUS_SUCCESS; } /* @@ -142,16 +239,61 @@ FsRtlInsertPerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, } /* - * @unimplemented + * @implemented */ PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI -FsRtlRemovePerFileObjectContext(IN PFILE_OBJECT PerFileObjectContext, +FsRtlRemovePerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL) { - KeBugCheck(FILE_SYSTEM); - return NULL; + PLIST_ENTRY NextEntry; + PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; + PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL; + + if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject))) + { + return NULL; + } + + ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); + + /* If list is empty, no need to browse it */ + if (!IsListEmpty(&(FOContext->FilterContexts))) + { + for (NextEntry = FOContext->FilterContexts.Flink; + NextEntry != &(FOContext->FilterContexts); + NextEntry = NextEntry->Flink) + { + /* If we don't have any criteria for search, first entry will be enough */ + if (!OwnerId && !InstanceId) + { + PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry; + break; + } + /* Else, we've to find something that matches with the parameters. */ + else + { + TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links); + if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) || + (OwnerId && TmpPerFOContext->OwnerId == OwnerId)) + { + PerFOContext = TmpPerFOContext; + break; + } + } + } + + /* Finally remove entry from list */ + if (PerFOContext) + { + RemoveEntryList(&(PerFOContext->Links)); + } + } + + ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); + + return PerFOContext; } /* @@ -197,6 +339,7 @@ FsRtlRemovePerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, } } } + /* Finally remove entry from list */ if (PerStreamContext) { diff --git a/reactos/ntoskrnl/include/internal/fsrtl.h b/reactos/ntoskrnl/include/internal/fsrtl.h index 7997abd41c3..b0777de94cc 100644 --- a/reactos/ntoskrnl/include/internal/fsrtl.h +++ b/reactos/ntoskrnl/include/internal/fsrtl.h @@ -53,6 +53,15 @@ FsRtlInitSystem( VOID ); +// +// File contexts Routines +// +VOID +NTAPI +FsRtlPTeardownPerFileObjectContexts( + IN PFILE_OBJECT FileObject +); + // // Global data inside the File System Runtime Library // diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index bf676b610f1..8edb68e75be 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -1155,6 +1155,20 @@ IopCloseFile( IN ULONG SystemHandleCount ); +PVOID +NTAPI +IoGetFileObjectFilterContext( + IN PFILE_OBJECT FileObject +); + +NTSTATUS +NTAPI +IoChangeFileObjectFilterContext( + IN PFILE_OBJECT FileObject, + IN PVOID FilterContext, + IN BOOLEAN Define +); + // // I/O Timer Routines // diff --git a/reactos/ntoskrnl/io/iomgr/file.c b/reactos/ntoskrnl/io/iomgr/file.c index 46060f470b2..43686de19d6 100644 --- a/reactos/ntoskrnl/io/iomgr/file.c +++ b/reactos/ntoskrnl/io/iomgr/file.c @@ -1049,6 +1049,13 @@ IopDeleteFile(IN PVOID ObjectBody) ExFreePool(FileObject->CompletionContext); } + /* Check if the FO had extension */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) + { + /* Release filter context structure if any */ + FsRtlPTeardownPerFileObjectContexts(FileObject); + } + /* Check if dereference has been done yet */ if (!DereferenceDone) { @@ -1610,6 +1617,36 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, return Status; } +PVOID +NTAPI +IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject) +{ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) + { + UNIMPLEMENTED; + /* FIXME: return NULL for the moment ~ */ + return NULL; + } + + return NULL; +} + +NTSTATUS +NTAPI +IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, + IN PVOID FilterContext, + IN BOOLEAN Define) +{ + if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) + { + return STATUS_INVALID_PARAMETER; + } + + UNIMPLEMENTED; + + return STATUS_NOT_IMPLEMENTED; +} + /* FUNCTIONS *****************************************************************/ /*