[RXCE]
[reactos.git] / reactos / sdk / lib / drivers / rxce / rxce.c
index 9cffb08..d293719 100644 (file)
@@ -69,6 +69,24 @@ NTAPI
 RxWorkItemDispatcher(
     PVOID Context);
 
+PVOID
+NTAPI
+_RxAllocatePoolWithTag(
+    _In_ POOL_TYPE PoolType,
+    _In_ SIZE_T NumberOfBytes,
+    _In_ ULONG Tag);
+
+VOID
+NTAPI
+_RxFreePool(
+    _In_ PVOID Buffer);
+
+VOID
+NTAPI
+_RxFreePoolWithTag(
+    _In_ PVOID Buffer,
+    _In_ ULONG Tag);
+
 extern ULONG ReadAheadGranularity;
 
 volatile LONG RxNumberOfActiveFcbs = 0;
@@ -86,12 +104,14 @@ RX_DISPATCHER RxDispatcher;
 RX_WORK_QUEUE_DISPATCHER RxDispatcherWorkQueues;
 FAST_MUTEX RxLowIoPagingIoSyncMutex;
 BOOLEAN RxContinueFromAssert = TRUE;
+ULONG RxExplodePoolTags = 1;
 #if DBG
 BOOLEAN DumpDispatchRoutine = TRUE;
 #else
 BOOLEAN DumpDispatchRoutine = FALSE;
 #endif
 
+#if RDBSS_ASSERTS
 #ifdef ASSERT
 #undef ASSERT
 #endif
@@ -101,6 +121,18 @@ BOOLEAN DumpDispatchRoutine = FALSE;
     {                                             \
         RxAssert(#exp, __FILE__, __LINE__, NULL); \
     }
+#endif
+
+#if RX_POOL_WRAPPER
+#undef RxAllocatePool
+#undef RxAllocatePoolWithTag
+#undef RxFreePool
+
+#define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
+#define RxAllocatePoolWithTag _RxAllocatePoolWithTag
+#define RxFreePool _RxFreePool
+#define RxFreePoolWithTag _RxFreePoolWithTag
+#endif
 
 /* FUNCTIONS ****************************************************************/
 
@@ -225,7 +257,7 @@ RxAllocateFcbObject(
     /* Otherwise, allocate it */
     else
     {
-        Buffer = ExAllocatePoolWithTag(PoolType, NameSize + FcbSize + SrvOpenSize + FobxSize + NonPagedSize, RX_FCB_POOLTAG);
+        Buffer = RxAllocatePoolWithTag(PoolType, NameSize + FcbSize + SrvOpenSize + FobxSize + NonPagedSize, RX_FCB_POOLTAG);
         if (Buffer == NULL)
         {
             return NULL;
@@ -260,10 +292,10 @@ RxAllocateFcbObject(
         /* If we were not allocated from non paged, allocate the NON_PAGED_FCB now */
         if (PoolType != NonPagedPool)
         {
-            NonPagedFcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NON_PAGED_FCB), RX_NONPAGEDFCB_POOLTAG);
+            NonPagedFcb = RxAllocatePoolWithTag(NonPagedPool, sizeof(NON_PAGED_FCB), RX_NONPAGEDFCB_POOLTAG);
             if (NonPagedFcb == NULL)
             {
-                ExFreePoolWithTag(Buffer, RX_FCB_POOLTAG);
+                RxFreePoolWithTag(Buffer, RX_FCB_POOLTAG);
                 return NULL;
             }
 
@@ -399,7 +431,7 @@ RxAllocateObject(
 
     /* Now, allocate the object */
     ObjectSize = ExtensionSize + StructSize + NameLength;
-    Object = ExAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
+    Object = RxAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
     if (Object == NULL)
     {
         return NULL;
@@ -731,7 +763,7 @@ RxConstructNetRoot(
     ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
 
     /* Allocate the context */
-    Context = ExAllocatePoolWithTag(PagedPool, sizeof(MRX_CREATENETROOT_CONTEXT), RX_SRVCALL_POOLTAG);
+    Context = RxAllocatePoolWithTag(PagedPool, sizeof(MRX_CREATENETROOT_CONTEXT), RX_SRVCALL_POOLTAG);
     if (Context == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -797,7 +829,7 @@ RxConstructNetRoot(
     RxTransitionVNetRoot(VirtualNetRoot, VRootCondition);
 
     /* Context is not longer needed */
-    ExFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
+    RxFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
 
     DPRINT("Status: %x\n", Status);
 
@@ -829,7 +861,7 @@ RxConstructSrvCall(
     ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
 
     /* Allocate the context for mini-rdr */
-    Calldown = ExAllocatePoolWithTag(NonPagedPool, sizeof(MRX_SRVCALLDOWN_STRUCTURE), RX_SRVCALL_POOLTAG);
+    Calldown = RxAllocatePoolWithTag(NonPagedPool, sizeof(MRX_SRVCALLDOWN_STRUCTURE), RX_SRVCALL_POOLTAG);
     if (Calldown == NULL)
     {
         SrvCall->Context = NULL;
@@ -1718,16 +1750,29 @@ RxDereference(
     RefCount = InterlockedDecrement((volatile long *)&Node->NodeReferenceCount);
     ASSERT(RefCount >= 0);
 
-    /* TODO: trace */
+    /* Trace refcount */
     switch (NodeType)
     {
         case RDBSS_NTC_SRVCALL:
+            PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_NETROOT:
+            PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_V_NETROOT:
+            PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_SRVOPEN:
+            PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_FOBX:
-            UNIMPLEMENTED;
+            PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
             break;
+
         default:
             ASSERT(FALSE);
             break;
@@ -1880,7 +1925,7 @@ RxDispatchToWorkerThread(
     PRX_WORK_DISPATCH_ITEM DispatchItem;
 
     /* Allocate a bit of context */
-    DispatchItem = ExAllocatePoolWithTag(PagedPool, sizeof(RX_WORK_DISPATCH_ITEM), RX_WORKQ_POOLTAG);
+    DispatchItem = RxAllocatePoolWithTag(PagedPool, sizeof(RX_WORK_DISPATCH_ITEM), RX_WORKQ_POOLTAG);
     if (DispatchItem == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -1896,7 +1941,7 @@ RxDispatchToWorkerThread(
     Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, DispatchItem);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+        RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
         DPRINT1("RxInsertWorkQueueItem failed! Queue: %ld, Routine: %p, Context: %p, Status: %lx\n", WorkQueueType, Routine, pContext, Status);
     }
 
@@ -2175,7 +2220,7 @@ RxFinalizeNetFcb(
                 Entry = ThisFcb->BufferedLocks.List;
                 ThisFcb->BufferedLocks.List = Entry->Next;
 
-                ExFreePool(Entry);
+                RxFreePool(Entry);
             }
         }
 
@@ -2208,7 +2253,7 @@ RxFinalizeNetFcb(
     /* Now, release everything */
     if (ThisFcb->pBufferingStateChangeCompletedEvent != NULL)
     {
-        ExFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
+        RxFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
     }
 
     if (ThisFcb->MRxDispatch != NULL)
@@ -2952,7 +2997,7 @@ RxFinishSrvCallConstruction(
 
     RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
     RxTransitionSrvCall(SrvCall, Condition);
-    ExFreePoolWithTag(Calldown, RX_SRVCALL_POOLTAG);
+    RxFreePoolWithTag(Calldown, RX_SRVCALL_POOLTAG);
 
     /* If async, finish it here, otherwise, caller has already finished the stuff */
     if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
@@ -2981,7 +3026,7 @@ RxFinishSrvCallConstruction(
             {
                 if (Context->Info.Buffer != NULL)
                 {
-                    ExFreePool(Context->Info.Buffer);
+                    RxFreePool(Context->Info.Buffer);
                     Context->Info.Buffer = NULL;
                 }
             }
@@ -4354,12 +4399,25 @@ RxpDereferenceAndFinalizeNetFcb(
     return Freed;
 }
 
+/*
+ * @implemented
+ */
 LONG
 RxpDereferenceNetFcb(
    PFCB Fcb)
 {
-    UNIMPLEMENTED;
-    return 0;
+    LONG NewCount;
+
+    PAGED_CODE();
+
+    ASSERT(NodeTypeIsFcb(Fcb));
+
+    NewCount = InterlockedDecrement((volatile long *)&Fcb->NodeReferenceCount);
+    ASSERT(NewCount >= 0);
+
+    PRINT_REF_COUNT(NETFCB, NewCount);
+
+    return NewCount;
 }
 
 /*
@@ -4478,12 +4536,24 @@ RxPrefixTableLookupName(
     return Container;
 }
 
+/*
+ * @implemented
+ */
 LONG
 RxpReferenceNetFcb(
    PFCB Fcb)
 {
-    UNIMPLEMENTED;
-    return 0;
+    LONG NewCount;
+
+    PAGED_CODE();
+
+    ASSERT(NodeTypeIsFcb(Fcb));
+
+    NewCount = InterlockedIncrement((volatile long *)&Fcb->NodeReferenceCount);
+
+    PRINT_REF_COUNT(NETFCB, Fcb->NodeReferenceCount);
+
+    return NewCount;
 }
 
 /*
@@ -4541,8 +4611,15 @@ RxpTrackDereference(
     _In_ ULONG Line,
     _In_ PVOID Instance)
 {
+    PAGED_CODE();
+
+    if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+    {
+        return TRUE;
+    }
+
     UNIMPLEMENTED;
-    return FALSE;
+    return TRUE;
 }
 
 VOID
@@ -4552,6 +4629,11 @@ RxpTrackReference(
     _In_ ULONG Line,
     _In_ PVOID Instance)
 {
+    if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+    {
+        return;
+    }
+
     UNIMPLEMENTED;
 }
 
@@ -4559,6 +4641,17 @@ VOID
 RxpUndoScavengerFinalizationMarking(
    PVOID Instance)
 {
+    PNODE_TYPE_AND_SIZE Node;
+
+    PAGED_CODE();
+
+    Node = (PNODE_TYPE_AND_SIZE)Instance;
+    /* There's no marking - nothing to do */
+    if (!BooleanFlagOn(Node->NodeTypeCode, RX_SCAVENGER_MASK))
+    {
+        return;
+    }
+
     UNIMPLEMENTED;
 }
 
@@ -4752,16 +4845,29 @@ RxReference(
     Node = (PNODE_TYPE_AND_SIZE)Instance;
     InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
 
-    /* And that's not implemented! (yay, we leak :-D) */
+    /* Trace refcount if asked */
     switch (NodeType)
     {
         case RDBSS_NTC_SRVCALL:
+            PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_NETROOT:
+            PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_V_NETROOT:
+            PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_SRVOPEN:
+            PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
+            break;
+
         case RDBSS_NTC_FOBX:
-            UNIMPLEMENTED;
+            PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
             break;
+
         default:
             ASSERT(FALSE);
             break;
@@ -5228,6 +5334,9 @@ RxTableLookupName_ExactLengthMatch(
     return NULL;
 }
 
+/*
+ * @implemented
+ */
 VOID
 RxTrackerUpdateHistory(
     _Inout_opt_ PRX_CONTEXT RxContext,
@@ -5237,7 +5346,74 @@ RxTrackerUpdateHistory(
     _In_ PCSTR FileName,
     _In_ ULONG SerialNumber)
 {
-    UNIMPLEMENTED;
+    PFCB Fcb;
+    RX_FCBTRACKER_CASES Case;
+
+    /* Check for null or special context */
+    if (RxContext == NULL)
+    {
+        Case = RX_FCBTRACKER_CASE_NULLCONTEXT;
+    }
+    else if ((ULONG_PTR)RxContext == -1)
+    {
+        Case = RX_FCBTRACKER_CASE_CBS_CONTEXT;
+    }
+    else if ((ULONG_PTR)RxContext == -2)
+    {
+        Case = RX_FCBTRACKER_CASE_CBS_WAIT_CONTEXT;
+    }
+    else
+    {
+        ASSERT(NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT);
+        Case = RX_FCBTRACKER_CASE_NORMAL;
+    }
+
+    /* If caller provided a FCB, update its history */
+    if (MrxFcb != NULL)
+    {
+        Fcb = (PFCB)MrxFcb;
+        ASSERT(NodeTypeIsFcb(Fcb));
+
+        /* Only one acquire operation, so many release operations... */
+        if (Operation == TRACKER_ACQUIRE_FCB)
+        {
+            ++Fcb->FcbAcquires[Case];
+        }
+        else
+        {
+            ++Fcb->FcbReleases[Case];
+        }
+    }
+
+    /* If we have a normal context, update its history about this function calls */
+    if (Case == RX_FCBTRACKER_CASE_NORMAL)
+    {
+        ULONG TrackerHistoryPointer;
+
+        /* Only one acquire operation, so many release operations... */
+        if (Operation == TRACKER_ACQUIRE_FCB)
+        {
+            InterlockedIncrement(&RxContext->AcquireReleaseFcbTrackerX);
+        }
+        else
+        {
+            InterlockedDecrement(&RxContext->AcquireReleaseFcbTrackerX);
+        }
+
+        /* We only keep track of the 32 first calls */
+        TrackerHistoryPointer = InterlockedExchangeAdd((volatile long *)&RxContext->TrackerHistoryPointer, 1);
+        if (TrackerHistoryPointer < RDBSS_TRACKER_HISTORY_SIZE)
+        {
+            RxContext->TrackerHistory[TrackerHistoryPointer].AcquireRelease = Operation;
+            RxContext->TrackerHistory[TrackerHistoryPointer].LineNumber = LineNumber;
+            RxContext->TrackerHistory[TrackerHistoryPointer].FileName = (PSZ)FileName;
+            RxContext->TrackerHistory[TrackerHistoryPointer].SavedTrackerValue = RxContext->AcquireReleaseFcbTrackerX;
+            RxContext->TrackerHistory[TrackerHistoryPointer].Flags = RxContext->Flags;
+        }
+
+        /* If it's negative, then we released once more than we acquired it?! */
+        ASSERT(RxContext->AcquireReleaseFcbTrackerX >= 0);
+    }
 }
 
 VOID
@@ -5265,17 +5441,17 @@ RxUninitializeVNetRootParameters(
     /* Only free what could have been allocated */
     if (UserName != NULL)
     {
-        ExFreePool(UserName);
+        RxFreePool(UserName);
     }
 
     if (UserDomainName != NULL)
     {
-        ExFreePool(UserDomainName);
+        RxFreePool(UserDomainName);
     }
 
     if (Password != NULL)
     {
-        ExFreePool(Password);
+        RxFreePool(Password);
     }
 
     /* And remove the possibly set CSC agent flag */
@@ -5329,11 +5505,112 @@ RxUpdateCondition(
     }
 }
 
+/*
+ * @implemented
+ */
 VOID
 RxVerifyOperationIsLegal(
     IN PRX_CONTEXT RxContext)
 {
-    UNIMPLEMENTED;
+    PIRP Irp;
+    PMRX_FOBX Fobx;
+    BOOLEAN FlagSet;
+    PFILE_OBJECT FileObject;
+    PIO_STACK_LOCATION Stack;
+
+    PAGED_CODE();
+
+    Irp = RxContext->CurrentIrp;
+    Stack = RxContext->CurrentIrpSp;
+    FileObject = Stack->FileObject;
+
+    /* We'll only check stuff on opened files, this requires an IRP and a FO */
+    if (Irp == NULL || FileObject == NULL)
+    {
+        return;
+    }
+
+    /* Set no exception for breakpoint - remember whether is was already set */
+    FlagSet = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT);
+    SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT);
+
+    /* If we have a CCB, perform a few checks on opened file */
+    Fobx = RxContext->pFobx;
+    if (Fobx != NULL)
+    {
+        PMRX_SRV_OPEN SrvOpen;
+
+        SrvOpen = Fobx->pSrvOpen;
+        if (SrvOpen != NULL)
+        {
+            UCHAR MajorFunction;
+
+            MajorFunction = RxContext->MajorFunction;
+            /* Only allow closing/cleanup operations on renamed files */
+            if (MajorFunction != IRP_MJ_CLEANUP && MajorFunction != IRP_MJ_CLOSE &&
+                BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED))
+            {
+                RxContext->IoStatusBlock.Status = STATUS_FILE_RENAMED;
+                ExRaiseStatus(STATUS_FILE_RENAMED);
+            }
+
+            /* Only allow closing/cleanup operations on deleted files */
+            if (MajorFunction != IRP_MJ_CLEANUP && MajorFunction != IRP_MJ_CLOSE &&
+                BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED))
+            {
+                RxContext->IoStatusBlock.Status = STATUS_FILE_DELETED;
+                ExRaiseStatus(STATUS_FILE_DELETED);
+            }
+        }
+    }
+
+    /* If that's an open operation */
+    if (RxContext->MajorFunction == IRP_MJ_CREATE)
+    {
+        PFILE_OBJECT RelatedFileObject;
+
+        /* We won't allow an open operation relative to a file to be deleted */
+        RelatedFileObject = FileObject->RelatedFileObject;
+        if (RelatedFileObject != NULL)
+        {
+            PMRX_FCB Fcb;
+
+            Fcb = RelatedFileObject->FsContext;
+            if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
+            {
+                RxContext->IoStatusBlock.Status = STATUS_DELETE_PENDING;
+                ExRaiseStatus(STATUS_DELETE_PENDING);
+            }
+        }
+    }
+
+    /* If cleanup was completed */
+    if (BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
+    {
+        if (!BooleanFlagOn(Irp->Flags, IRP_PAGING_IO))
+        {
+            UCHAR MajorFunction;
+
+            /* We only allow a subset of operations (see FatVerifyOperationIsLegal for instance) */
+            MajorFunction = Stack->MajorFunction;
+            if (MajorFunction != IRP_MJ_CLOSE && MajorFunction != IRP_MJ_QUERY_INFORMATION &&
+                MajorFunction != IRP_MJ_SET_INFORMATION)
+            {
+                if ((MajorFunction != IRP_MJ_READ && MajorFunction != IRP_MJ_WRITE) ||
+                    !BooleanFlagOn(Stack->MinorFunction, IRP_MN_COMPLETE))
+                {
+                    RxContext->IoStatusBlock.Status = STATUS_FILE_CLOSED;
+                    ExRaiseStatus(STATUS_FILE_CLOSED);
+                }
+            }
+        }
+    }
+
+    /* If flag was already set, don't clear it */
+    if (!FlagSet)
+    {
+        ClearFlag(RxContext->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT);
+    }
 }
 
 /*
@@ -5406,7 +5683,43 @@ RxWorkItemDispatcher(
 
     DispatchItem->DispatchRoutine(DispatchItem->DispatchRoutineParameter);
 
-    ExFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+    RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+}
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+_RxAllocatePoolWithTag(
+    _In_ POOL_TYPE PoolType,
+    _In_ SIZE_T NumberOfBytes,
+    _In_ ULONG Tag)
+{
+    return ExAllocatePoolWithTagPriority(PoolType, NumberOfBytes, Tag, LowPoolPriority);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+_RxFreePool(
+    _In_ PVOID Buffer)
+{
+    ExFreePoolWithTag(Buffer, 0);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+_RxFreePoolWithTag(
+    _In_ PVOID Buffer,
+    _In_ ULONG Tag)
+{
+    ExFreePoolWithTag(Buffer, Tag);
 }
 
 NTSTATUS