diff --git a/ntoskrnl/io/iomgr/file.c b/ntoskrnl/io/iomgr/file.c index 0a5e0b1d1a1..860348a370e 100644 --- a/ntoskrnl/io/iomgr/file.c +++ b/ntoskrnl/io/iomgr/file.c @@ -2458,14 +2458,41 @@ IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, IN PVOID FilterContext, IN BOOLEAN Define) { + ULONG_PTR Success; + PFILE_OBJECT_EXTENSION FileObjectExtension; + if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) { return STATUS_INVALID_PARAMETER; } - UNIMPLEMENTED; + FileObjectExtension = FileObject->FileObjectExtension; + if (Define) + { + /* If define, just set the new value if not value is set + * Success will only contain old value. It is valid if it is NULL + */ + Success = InterlockedCompareExchange((volatile LONG *)&FileObjectExtension->FilterContext, (ULONG_PTR)FilterContext, 0); + } + else + { + /* If not define, we want to reset filter context. + * We will remove value (provided by the caller) and set NULL instead. + * This will only success if caller provides correct previous value. + * To catch whether it worked, we substract previous value to expect value: + * If it matches (and thus, we reset), Success will contain 0 + * Otherwise, it will contain a non-zero value. + */ + Success = InterlockedCompareExchange((volatile LONG *)&FileObjectExtension->FilterContext, 0, (ULONG_PTR)FilterContext) - (ULONG_PTR)FilterContext; + } - return STATUS_NOT_IMPLEMENTED; + /* If success isn't 0, it means we failed somewhere (set or unset) */ + if (Success != 0) + { + return STATUS_ALREADY_COMMITTED; + } + + return STATUS_SUCCESS; } NTSTATUS