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;
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
{ \
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 ****************************************************************/
/* 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;
/* 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;
}
/* Now, allocate the object */
ObjectSize = ExtensionSize + StructSize + NameLength;
- Object = ExAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
+ Object = RxAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
if (Object == NULL)
{
return NULL;
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;
RxTransitionVNetRoot(VirtualNetRoot, VRootCondition);
/* Context is not longer needed */
- ExFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
+ RxFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
DPRINT("Status: %x\n", Status);
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;
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;
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;
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);
}
Entry = ThisFcb->BufferedLocks.List;
ThisFcb->BufferedLocks.List = Entry->Next;
- ExFreePool(Entry);
+ RxFreePool(Entry);
}
}
/* Now, release everything */
if (ThisFcb->pBufferingStateChangeCompletedEvent != NULL)
{
- ExFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
+ RxFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
}
if (ThisFcb->MRxDispatch != NULL)
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))
{
if (Context->Info.Buffer != NULL)
{
- ExFreePool(Context->Info.Buffer);
+ RxFreePool(Context->Info.Buffer);
Context->Info.Buffer = NULL;
}
}
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;
}
/*
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;
}
/*
_In_ ULONG Line,
_In_ PVOID Instance)
{
+ PAGED_CODE();
+
+ if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+ {
+ return TRUE;
+ }
+
UNIMPLEMENTED;
- return FALSE;
+ return TRUE;
}
VOID
_In_ ULONG Line,
_In_ PVOID Instance)
{
+ if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+ {
+ return;
+ }
+
UNIMPLEMENTED;
}
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;
}
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;
return NULL;
}
+/*
+ * @implemented
+ */
VOID
RxTrackerUpdateHistory(
_Inout_opt_ PRX_CONTEXT RxContext,
_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
/* 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 */
}
}
+/*
+ * @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);
+ }
}
/*
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