[RXCE]
authorPierre Schweitzer <pierre@reactos.org>
Sat, 8 Jul 2017 17:12:33 +0000 (17:12 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 8 Jul 2017 17:12:33 +0000 (17:12 +0000)
- Define RxShouldPostCompletion() and use it
- Define RxIsResourceOwnershipStateExclusive() and use it
- Define some magic values

[RDBSS]
- Implement CheckForLoudOperations(), RxAdjustFileTimesAndSize(), RxIsOkToPurgeFcb()
- Continue implementation of RxCommonCleanup()
- Fix bugs in the RxCommonCleanup() implementation and make it more explicit when in the delete on close path
- Stub RxCleanupPipeQueues(), RxLowIoLockControlShell()
- Silent a few DPRINTs

CORE-8204
CORE-11327

svn path=/trunk/; revision=75307

reactos/sdk/include/ddk/fcb.h
reactos/sdk/include/ddk/mrx.h
reactos/sdk/include/ddk/ntrxdef.h
reactos/sdk/include/ddk/rxprocs.h
reactos/sdk/lib/drivers/rdbsslib/rdbss.c
reactos/sdk/lib/drivers/rxce/rxce.c

index 2b53c19..a32d0c7 100644 (file)
@@ -200,6 +200,7 @@ typedef struct _FCB
 } FCB, *PFCB;
 
 #define FCB_STATE_DELETE_ON_CLOSE 0x00000001
+#define FCB_STATE_TRUNCATE_ON_CLOSE 0x00000002
 #define FCB_STATE_PAGING_FILE 0x00000004
 #define FCB_STATE_DISABLE_LOCAL_BUFFERING 0x00000010
 #define FCB_STATE_TEMPORARY 0x00000020
@@ -287,6 +288,9 @@ typedef struct _SRV_OPEN
 
 #define FOBX_FLAG_MATCH_ALL 0x10000
 #define FOBX_FLAG_FREE_UNICODE 0x20000
+#define FOBX_FLAG_USER_SET_LAST_WRITE 0x40000
+#define FOBX_FLAG_USER_SET_LAST_ACCESS 0x80000
+#define FOBX_FLAG_USER_SET_LAST_CHANGE 0x200000
 #define FOBX_FLAG_DELETE_ON_CLOSE 0x800000
 #define FOBX_FLAG_SRVOPEN_CLOSED 0x1000000
 #define FOBX_FLAG_UNC_NAME 0x2000000
index e6bb83e..2115646 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _RXMINIRDR_
 #define _RXMINIRDR_
 
+#define RxShouldPostCompletion() ((KeGetCurrentIrql() >= DISPATCH_LEVEL))
+
 #define RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS 0x00000001
 #define RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS 0x00000002
 #define RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH 0x00000004
@@ -313,6 +315,7 @@ typedef struct _LOWIO_CONTEXT
 } LOWIO_CONTEXT;
 
 #define LOWIO_CONTEXT_FLAG_SYNCCALL 0x01
+#define LOWIO_CONTEXT_FLAG_SAVEUNLOCKS 0x2
 #define LOWIO_CONTEXT_FLAG_LOUDOPS 0x04
 #define LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL 0x08
 
index 424bdf8..da3a9ac 100644 (file)
@@ -9,9 +9,13 @@
 #define RxAllocatePoolWithTag ExAllocatePoolWithTag
 #define RxFreePool ExFreePool
 
+#define RxIsResourceOwnershipStateExclusive(Resource) (FlagOn((Resource)->Flag, ResourceOwnedExclusive))
+
 #define RxMdlIsLocked(Mdl) ((Mdl)->MdlFlags & MDL_PAGES_LOCKED)
 #define RxMdlSourceIsNonPaged(Mdl) ((Mdl)->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL)
 
+#define RxGetRequestorProcess(RxContext) IoGetRequestorProcess(RxContext->CurrentIrp)
+
 #define RxAdjustAllocationSizeforCC(Fcb)                                                       \
 {                                                                                              \
     if ((Fcb)->Header.FileSize.QuadPart > (Fcb)->Header.AllocationSize.QuadPart)               \
index 68c5f1d..63080ce 100644 (file)
@@ -116,6 +116,9 @@ RxMapSystemBuffer(
 #define FCB_MODE_SHARED_WAIT_FOR_EXCLUSIVE 3
 #define FCB_MODE_SHARED_STARVE_EXCLUSIVE 4
 
+#define CHANGE_BUFFERING_STATE_CONTEXT ((PRX_CONTEXT)IntToPtr(0xffffffff))
+#define CHANGE_BUFFERING_STATE_CONTEXT_WAIT ((PRX_CONTEXT)IntToPtr(0xfffffffe))
+
 NTSTATUS
 __RxAcquireFcb(
     _Inout_ PFCB Fcb,
@@ -374,6 +377,18 @@ RxFindOrConstructVirtualNetRoot(
     _In_ PUNICODE_STRING RemainingName);
 #endif
 
+#if (_WIN32_WINNT >= 0x0600)
+NTSTATUS
+RxLowIoLockControlShell(
+    _In_ PRX_CONTEXT RxContext,
+    _In_ PIRP Irp,
+    _In_ PFCB Fcb);
+#else
+NTSTATUS
+RxLowIoLockControlShell(
+    _In_ PRX_CONTEXT RxContext);
+#endif
+
 NTSTATUS
 NTAPI
 RxChangeBufferingState(
index e1f30e6..d297a46 100644 (file)
@@ -491,6 +491,7 @@ NPAGED_LOOKASIDE_LIST RxContextLookasideList;
 FAST_MUTEX RxContextPerFileSerializationMutex;
 RDBSS_DATA RxData;
 FCB RxDeviceFCB;
+BOOLEAN RxLoudLowIoOpsEnabled = FALSE;
 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
 {
     { RxCommonDispatchProblem },
@@ -593,11 +594,31 @@ DECLARE_CONST_UNICODE_STRING(unknownId, L"???");
 
 /* FUNCTIONS ****************************************************************/
 
+/*
+ * @implemented
+ */
 VOID
 CheckForLoudOperations(
     PRX_CONTEXT RxContext)
 {
-    UNIMPLEMENTED;
+    PAGED_CODE();
+
+#define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
+
+    /* Are loud operations enabled? */
+    if (RxLoudLowIoOpsEnabled)
+    {
+        PFCB Fcb;
+
+        /* If so, the operation will be loud only if filename ends with all.scr */
+        Fcb = (PFCB)RxContext->pFcb;
+        if (RtlCompareMemory(Add2Ptr(Fcb->PrivateAlreadyPrefixedName.Buffer, (Fcb->PrivateAlreadyPrefixedName.Length - ALLSCR_LENGTH)),
+                             L"all.scr", ALLSCR_LENGTH) == ALLSCR_LENGTH)
+        {
+            SetFlag(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_LOUDOPS);
+        }
+    }
+#undef ALLSCR_LENGTH
 }
 
 /*
@@ -746,6 +767,106 @@ RxAddToWorkque(
     ExQueueWorkItem((PWORK_QUEUE_ITEM)&RxContext->WorkQueueItem, Queue);
 }
 
+/*
+ * @implemented
+ */
+VOID
+RxAdjustFileTimesAndSize(
+    PRX_CONTEXT Context)
+{
+    PFCB Fcb;
+    PFOBX Fobx;
+    NTSTATUS Status;
+    PFILE_OBJECT FileObject;
+    LARGE_INTEGER CurrentTime;
+    FILE_BASIC_INFORMATION FileBasicInfo;
+    FILE_END_OF_FILE_INFORMATION FileEOFInfo;
+    BOOLEAN FileModified, SetLastChange, SetLastAccess, SetLastWrite, NeedUpdate;
+
+    PAGED_CODE();
+
+    FileObject = Context->CurrentIrpSp->FileObject;
+    /* If Cc isn't initialized, the file was not read nor written, nothing to do */
+    if (FileObject->PrivateCacheMap == NULL)
+    {
+        return;
+    }
+
+    /* Get now */
+    KeQuerySystemTime(&CurrentTime);
+
+    Fobx = (PFOBX)Context->pFobx;
+    /* Was the file modified? */
+    FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
+    /* We'll set last write if it was modified and user didn't update yet */
+    SetLastWrite = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE);
+    /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
+    SetLastAccess = SetLastWrite ||
+                    (BooleanFlagOn(FileObject->Flags, FO_FILE_FAST_IO_READ) &&
+                     !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS));
+    /* We'll set last change if it was modified and user didn't update yet */
+    SetLastChange = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE);
+
+    /* Nothing to update? Job done */
+    if (!FileModified && !SetLastWrite && !SetLastAccess && !SetLastChange)
+    {
+        return;
+    }
+
+    Fcb = (PFCB)Context->pFcb;
+    /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
+    NeedUpdate = FALSE;
+    RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
+
+    /* Update lastwrite time if required */
+    if (SetLastWrite)
+    {
+        NeedUpdate = TRUE;
+        Fcb->LastWriteTime.QuadPart = CurrentTime.QuadPart;
+        FileBasicInfo.LastWriteTime.QuadPart = CurrentTime.QuadPart;
+    }
+
+    /* Update lastaccess time if required */
+    if (SetLastAccess)
+    {
+        NeedUpdate = TRUE;
+        Fcb->LastAccessTime.QuadPart = CurrentTime.QuadPart;
+        FileBasicInfo.LastAccessTime.QuadPart = CurrentTime.QuadPart;
+    }
+
+    /* Update lastchange time if required */
+    if (SetLastChange)
+    {
+        NeedUpdate = TRUE;
+        Fcb->LastChangeTime.QuadPart = CurrentTime.QuadPart;
+        FileBasicInfo.ChangeTime.QuadPart = CurrentTime.QuadPart;
+    }
+
+    /* If one of the date was modified, issue a call to mini-rdr */
+    if (NeedUpdate)
+    {
+        Context->Info.FileInformationClass = FileBasicInformation;
+        Context->Info.Buffer = &FileBasicInfo;
+        Context->Info.Length = sizeof(FileBasicInfo);
+
+        MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
+        (void)Status;
+    }
+
+    /* If the file was modified, update its EOF */
+    if (FileModified)
+    {
+        FileEOFInfo.EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
+
+        Context->Info.FileInformationClass = FileEndOfFileInformation;
+        Context->Info.Buffer = &FileEOFInfo;
+        Context->Info.Length = sizeof(FileEOFInfo);
+
+        MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
+        (void)Status;
+    }
+}
+
 /*
  * @implemented
  */
@@ -1069,6 +1190,13 @@ RxCheckShareAccessPerSrvOpens(
     return STATUS_SUCCESS;
 }
 
+VOID
+RxCleanupPipeQueues(
+    PRX_CONTEXT Context)
+{
+    UNIMPLEMENTED;
+}
+
 /*
  * @implemented
  */
@@ -1462,8 +1590,9 @@ RxCommonCleanup(
     NTSTATUS Status;
     PNET_ROOT NetRoot;
     PFILE_OBJECT FileObject;
-    PLARGE_INTEGER TruncateSize;
-    BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired;
+    LARGE_INTEGER TruncateSize;
+    PLARGE_INTEGER TruncateSizePtr;
+    BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired, LeftForDelete;
 
     PAGED_CODE();
 
@@ -1545,12 +1674,13 @@ RxCommonCleanup(
 
     NetRoot = (PNET_ROOT)Fcb->pNetRoot;
     FcbTableAcquired = FALSE;
-    OneLeft = FALSE;
+    LeftForDelete = FALSE;
+    OneLeft = (Fcb->UncleanCount == 1);
 
     _SEH2_TRY
     {
         /* Unclean count and delete on close? Verify whether we're the one */
-        if (Fcb->UncleanCount == 1 && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
+        if (OneLeft && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
         {
             if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
             {
@@ -1572,9 +1702,10 @@ RxCommonCleanup(
                 FcbTableAcquired = TRUE;
             }
 
+            /* That means we'll perform the delete on close! */
             if (Fcb->UncleanCount == 1)
             {
-                OneLeft = TRUE;
+                LeftForDelete = TRUE;
             }
             else
             {
@@ -1584,18 +1715,82 @@ RxCommonCleanup(
         }
 
         IsFile = FALSE;
-        TruncateSize = NULL;
+        TruncateSizePtr = NULL;
         /* Handle cleanup for pipes and printers */
         if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
         {
-            UNIMPLEMENTED;
+            RxCleanupPipeQueues(Context);
         }
         /* Handle cleanup for files */
         else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
         {
+            Context->LowIoContext.Flags |= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS;
             if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
             {
-                UNIMPLEMENTED;
+                /* First, unlock */
+                FsRtlFastUnlockAll(&Fcb->Specific.Fcb.FileLock, FileObject, RxGetRequestorProcess(Context), Context);
+
+                /* If there are still locks to release, proceed */
+                if (Context->LowIoContext.ParamsFor.Locks.LockList != NULL)
+                {
+                    RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_UNLOCK_MULTIPLE);
+                    Context->LowIoContext.ParamsFor.Locks.Flags = 0;
+                    Status = RxLowIoLockControlShell(Context);
+                }
+
+                /* Fix times and size */
+                RxAdjustFileTimesAndSize(Context);
+
+                /* If we're the only one left... */
+                if (OneLeft)
+                {
+                    /* And if we're supposed to delete on close */
+                    if (LeftForDelete)
+                    {
+                        /* Update the sizes */
+                        RxAcquirePagingIoResource(Context, Fcb);
+                        Fcb->Header.FileSize.QuadPart = 0;
+                        Fcb->Header.ValidDataLength.QuadPart = 0;
+                        RxReleasePagingIoResource(Context, Fcb);
+                    }
+                    /* Otherwise, call the mini-rdr to adjust sizes */
+                    else
+                    {
+                        /* File got grown up, fill with zeroes */
+                        if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
+                            (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart))
+                        {
+                            MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxZeroExtend, (Context));
+                            Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
+                        }
+
+                        /* File was truncated, let mini-rdr proceed */
+                        if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE))
+                        {
+                            MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxTruncate, (Context));
+                            ClearFlag(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE);
+
+                            /* Keep track of file change for Cc uninit */
+                            TruncateSize.QuadPart = Fcb->Header.FileSize.QuadPart;
+                            TruncateSizePtr = &TruncateSize;
+                        }
+                    }
+                }
+
+                /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
+                if (NeedPurge)
+                {
+                    if (!OneLeft)
+                    {
+                        NeedPurge = FALSE;
+                    }
+                }
+                /* Otherwise, try to see whether we can purge */
+                else
+                {
+                    NeedPurge = (OneLeft && (LeftForDelete || !BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED)));
+                }
+
                 IsFile = TRUE;
             }
         }
@@ -1622,7 +1817,7 @@ RxCommonCleanup(
             if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
                 Fcb->UncleanCount == Fcb->UncachedUncleanCount)
             {
-                DPRINT1("Flushing %p due to last cached handle cleanup\n", Context);
+                DPRINT("Flushing %p due to last cached handle cleanup\n", Context);
                 RxFlushFcbInSystemCache(Fcb, TRUE);
             }
         }
@@ -1631,7 +1826,7 @@ RxCommonCleanup(
             /* Always */
             if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
             {
-                DPRINT1("Flushing %p on cleanup\n", Context);
+                DPRINT("Flushing %p on cleanup\n", Context);
                 RxFlushFcbInSystemCache(Fcb, TRUE);
             }
         }
@@ -1644,32 +1839,32 @@ RxCommonCleanup(
                 if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
                     Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
                 {
-                    DPRINT1("Flushing FCB in system cache for %p\n", Context);
+                    DPRINT("Flushing FCB in system cache for %p\n", Context);
                     RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
                 }
             }
         }
 
-        /* If purge required, flush */
-        if (!OneLeft && NeedPurge)
+        /* If purge required, and not about to delete, flush */
+        if (!LeftForDelete && NeedPurge)
         {
-            DPRINT1("Flushing FCB in system cache for %p\n", Context);
+            DPRINT("Flushing FCB in system cache for %p\n", Context);
             RxFlushFcbInSystemCache(Fcb, TRUE);
         }
 
         /* If it was a file, drop cache */
         if (IsFile)
         {
-            DPRINT1("Uninit cache map for file\n");
-            RxUninitializeCacheMap(Context, FileObject, TruncateSize);
+            DPRINT("Uninit cache map for file\n");
+            RxUninitializeCacheMap(Context, FileObject, TruncateSizePtr);
         }
 
-        /* If that's the one left, or if it needs purge, flush */
-        if (OneLeft || NeedPurge)
+        /* If that's the one left for deletion, or if it needs purge, flush */
+        if (LeftForDelete || NeedPurge)
         {
-            RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !OneLeft);
-            /* Also remove from FCB table */
-            if (OneLeft)
+            RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !LeftForDelete);
+            /* If that's for deletion, also remove from FCB table */
+            if (LeftForDelete)
             {
                 RxRemoveNameNetFcb(Fcb);
                 RxReleaseFcbTableLock(&NetRoot->FcbTable);
@@ -4943,12 +5138,43 @@ RxIsMemberOfTopLevelIrpAllocatedContextsList(
     return Found;
 }
 
+/*
+ * @implemented
+ */
 BOOLEAN
 RxIsOkToPurgeFcb(
     PFCB Fcb)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    PLIST_ENTRY Entry;
+
+    /* No associated SRV_OPEN, it's OK to purge */
+    if (IsListEmpty(&Fcb->SrvOpenList))
+    {
+        return TRUE;
+    }
+
+    /* Only allow to purge if all the associated SRV_OPEN
+     * - have no outstanding opens ongoing
+     * - have only read attribute set
+     */
+    for (Entry = Fcb->SrvOpenList.Flink;
+         Entry != &Fcb->SrvOpenList;
+         Entry = Entry->Flink)
+    {
+        PSRV_OPEN SrvOpen;
+
+        SrvOpen = CONTAINING_RECORD(Entry, SRV_OPEN, SrvOpenQLinks);
+
+        /* Failing previous needs, don't allow purge */
+        if (SrvOpen->UncleanFobxCount != 0 ||
+            (SrvOpen->DesiredAccess & 0xFFEFFFFF) != FILE_READ_ATTRIBUTES)
+        {
+            return FALSE;
+        }
+    }
+
+    /* All correct, allow purge */
+    return TRUE;
 }
 
 /*
@@ -5091,6 +5317,14 @@ RxLowIoIoCtlShellCompletion(
     return Status;
 }
 
+NTSTATUS
+RxLowIoLockControlShell(
+    IN PRX_CONTEXT RxContext)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 /*
  * @implemented
  */
index a19832a..9618ec9 100644 (file)
@@ -5116,7 +5116,7 @@ RxLowIoCompletionTail(
     DPRINT("RxLowIoCompletionTail(%p)\n", RxContext);
 
     /* Only continue if we're at APC_LEVEL or lower */
-    if (KeGetCurrentIrql() >= DISPATCH_LEVEL &&
+    if (RxShouldPostCompletion() &&
         !BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL))
     {
         return STATUS_MORE_PROCESSING_REQUIRED;
@@ -5755,7 +5755,8 @@ RxpDereferenceAndFinalizeNetFcb(
 
             if (!RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
             {
-                if (RxContext != NULL && RxContext != (PVOID)-1 && RxContext != (PVOID)-2)
+                if (RxContext != NULL && RxContext != CHANGE_BUFFERING_STATE_CONTEXT &&
+                    RxContext != CHANGE_BUFFERING_STATE_CONTEXT_WAIT)
                 {
                     RxContext->Flags |= RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
                 }
@@ -7807,11 +7808,11 @@ RxTrackerUpdateHistory(
     {
         Case = RX_FCBTRACKER_CASE_NULLCONTEXT;
     }
-    else if ((ULONG_PTR)RxContext == -1)
+    else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT)
     {
         Case = RX_FCBTRACKER_CASE_CBS_CONTEXT;
     }
-    else if ((ULONG_PTR)RxContext == -2)
+    else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT)
     {
         Case = RX_FCBTRACKER_CASE_CBS_WAIT_CONTEXT;
     }
@@ -8211,7 +8212,7 @@ __RxAcquireFcb(
     SpecialContext = FALSE;
     ContextIsPresent = FALSE;
     /* Check for special context */
-    if ((ULONG_PTR)RxContext == -1 || (ULONG_PTR)RxContext == -2)
+    if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT || RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT)
     {
         SpecialContext = TRUE;
     }
@@ -8374,7 +8375,7 @@ __RxReleaseFcb(
     RxAcquireSerializationMutex();
 
     BufferingPending = BooleanFlagOn(MrxFcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING);
-    IsExclusive = BooleanFlagOn(MrxFcb->Header.Resource->Flag, ResourceOwnedExclusive);
+    IsExclusive = !!RxIsResourceOwnershipStateExclusive(MrxFcb->Header.Resource);
 
     /* If no buffering pending, or no exclusive lock (we can only handle with an exclusive lock),
      * then just release the FCB
@@ -8421,7 +8422,7 @@ __RxReleaseFcbForThread(
     RxAcquireSerializationMutex();
 
     BufferingPending = BooleanFlagOn(MrxFcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING);
-    IsExclusive = BooleanFlagOn(MrxFcb->Header.Resource->Flag, ResourceOwnedExclusive);
+    IsExclusive = !!RxIsResourceOwnershipStateExclusive(MrxFcb->Header.Resource);
 
     /* If no buffering pending, or no exclusive lock (we can only handle with an exclusive lock),
      * then just release the FCB