VOID ClasspUninitializeRemoveTracking( _In_ PDEVICE_OBJECT DeviceObject ) { #if DBG PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PRTL_GENERIC_TABLE removeTrackingList = commonExtension->RemoveTrackingList; ASSERTMSG("Removing the device while still holding remove locks", commonExtension->RemoveTrackingUntrackedCount == 0 && removeTrackingList != NULL ? RtlNumberGenericTableElements(removeTrackingList) == 0 : TRUE); if (removeTrackingList != NULL) { KIRQL oldIrql; KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, &oldIrql); FREE_POOL(removeTrackingList); commonExtension->RemoveTrackingList = NULL; KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql); } #else UNREFERENCED_PARAMETER(DeviceObject); #endif }
static void RtlSplayTreeTest() { ULONG i, del; PCHAR Ch; CHAR Text[] = "the quick_brown!fOx-jUmp3d/0vER+THe^lazy.D@g"; CHAR NewE[] = "11111111111111111111111111111111110111111111"; RTL_GENERIC_TABLE Table; RtlInitializeGenericTable (&Table, CompareCharTable, AllocRoutine, FreeRoutine, NULL); for (i = 0; Text[i]; i++) { BOOLEAN WasNew; Ch = (PCHAR)RtlInsertElementGenericTable (&Table, &Text[i], sizeof(Text[i]), &WasNew); ok(Ch && *Ch == Text[i], "Copy character into node\n"); ok(WasNew == (NewE[i] == '1'), "Character newness didn't match for char %u: '%c'\n", i, Text[i]); } for (Ch = (PCHAR)RtlEnumerateGenericTable(&Table, TRUE), i = 0; Ch; Ch = (PCHAR)RtlEnumerateGenericTable(&Table, FALSE), i++) { ok(strchr(Text, *Ch) != NULL, "Nonexistent character\n"); } ok(RtlNumberGenericTableElements(&Table) == strlen(Text) - 1, "Not the right number of elements\n"); ok(RtlLookupElementGenericTable(&Table, "q") != NULL, "Could not lookup q\n"); ok(!RtlLookupElementGenericTable(&Table, "#"), "Found a character that shouldn't appear\n"); ok(strlen(Text) == i + 1, "Didn't enumerate enough characters\n"); del = 0; for (i = 0; Text[i]; i++) { if (NewE[i] == '1') { BOOLEAN WasDeleted; WasDeleted = RtlDeleteElementGenericTable(&Table, &Text[i]); del += WasDeleted; } } ok(!RtlNumberGenericTableElements(&Table), "Not zero elements\n"); ok(!RtlGetElementGenericTable(&Table, 0), "Elements left when we removed them all\n"); ok(strlen(Text) == del + 1, "Deleted too many times\n"); ok(IsListEmpty(&Allocations), "Didn't free all memory\n"); }
/* * @implemented */ VOID NTAPI FsRtlResetBaseMcb(IN PBASE_MCB OpaqueMcb) { PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb; PLARGE_MCB_MAPPING_ENTRY Element; while (RtlNumberGenericTableElements(&Mcb->Mapping->Table) && (Element = (PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(&Mcb->Mapping->Table, 0))) { RtlDeleteElementGenericTable(&Mcb->Mapping->Table, Element); } Mcb->PairCount = 0; Mcb->MaximumPairCount = 0; }
ULONG NTAPI MiCacheEvictPages(PMM_SECTION_SEGMENT Segment, ULONG Target) { ULONG_PTR Entry; ULONG Result = 0, i, j; NTSTATUS Status; PFN_NUMBER Page; LARGE_INTEGER Offset; MmLockSectionSegment(Segment); for (i = 0; i < RtlNumberGenericTableElements(&Segment->PageTable); i++) { PCACHE_SECTION_PAGE_TABLE Element = RtlGetElementGenericTable(&Segment->PageTable, i); ASSERT(Element); Offset = Element->FileOffset; for (j = 0; j < ENTRIES_PER_ELEMENT; j++, Offset.QuadPart += PAGE_SIZE) { Entry = MmGetPageEntrySectionSegment(Segment, &Offset); if (Entry && !IS_SWAP_FROM_SSE(Entry)) { Page = PFN_FROM_SSE(Entry); MmUnlockSectionSegment(Segment); Status = MmpPageOutPhysicalAddress(Page); if (NT_SUCCESS(Status)) Result++; MmLockSectionSegment(Segment); } } } MmUnlockSectionSegment(Segment); return Result; }
/* * @implemented */ ULONG NTAPI FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb) { PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb; LONGLONG LbnAtVbn0 = -1; ULONG Nodes = RtlNumberGenericTableElements(&Mcb->Mapping->Table); if (Nodes == 0) return 0; FsRtlLookupBaseMcbEntry(OpaqueMcb, 0, /* Vbn */ &LbnAtVbn0, /* Lbn */ NULL, NULL, NULL, NULL); /* 4 output arguments - not interested in them */ /* Return the count */ //return Mcb->PairCount; /* Return the number of 'real' and 'hole' runs. * If we do not have sector 0 as 'real' emulate a 'hole' there. */ return Nodes * 2 - (LbnAtVbn0 != -1 ? 1 : 0); /* include holes as runs */ }
VOID DumpVcb ( IN ULONG Address, IN ULONG Options ) /*++ Routine Description: Dump a Vcb. Arguments: Address - Gives the address of the Vcb to dump Options - If 1, we also dump the root Lcb and the Fcb table If 2, we dump everything for option 1, and also dump the Fcbs in the Fcb table Return Value: None --*/ { ULONG Result; PVCB pVcb; VCB Vcb; PFCB pFcb; FCB_TABLE_ELEMENT FcbTableElement; PFCB_TABLE_ELEMENT pFcbTableElement; RTL_GENERIC_TABLE FcbTable; PRTL_GENERIC_TABLE pFcbTable; PVOID RestartKey; dprintf( "\n Vcb @ %08lx", Address ); pVcb = (PVCB) Address; if ( !ReadMemory( (DWORD) pVcb, &Vcb, sizeof( Vcb ), &Result) ) { dprintf( "%08lx: Unable to read pVcb\n", pVcb ); return; } if (Vcb.NodeTypeCode != NTFS_NTC_VCB) { dprintf( "\nVCB signature does not match, probably not a VCB" ); return; } PrintState( VcbState, Vcb.VcbState ); DUMP_WITH_OFFSET( VCB, Vcb, CleanupCount, "CleanupCount: " ); DUMP_WITH_OFFSET( VCB, Vcb, CloseCount, "CloseCount: " ); DUMP_WITH_OFFSET( VCB, Vcb, ReadOnlyCloseCount, "ReadOnlyCloseCount: " ); DUMP_WITH_OFFSET( VCB, Vcb, SystemFileCloseCount, "SystemFileCloseCount:" ); DUMP_WITH_OFFSET( VCB, Vcb, MftScb, "MftScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, Mft2Scb, "Mft2Scb: " ); DUMP_WITH_OFFSET( VCB, Vcb, LogFileScb, "LogFileScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, VolumeDasdScb, "VolumeDasdScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, RootIndexScb, "RootIndexScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, BitmapScb, "BitmapScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, AttributeDefTableScb, "AttributeDefTableScb:" ); DUMP_WITH_OFFSET( VCB, Vcb, UpcaseTableScb, "UpcaseTableScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, BadClusterFileScb, "BadClusterFileScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, QuotaTableScb, "QuotaTableScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, OwnerIdTableScb, "OwnerIdTableScb: " ); DUMP_WITH_OFFSET( VCB, Vcb, MftBitmapScb, "MftBitmapScb: " ); if (Options >= 1) { DumpLcb( (ULONG) Vcb.RootLcb, 0 ); } else { DUMP_WITH_OFFSET( VCB, Vcb, RootLcb, "RootLcb: " ); } // // Dump the FcbTable // if (Options >= 1) { pFcbTable = &(pVcb->FcbTable); if ( !ReadMemory( (DWORD) pFcbTable, &FcbTable, sizeof( FcbTable ), &Result) ) { dprintf( "%08lx: Unable to read pFcbTable\n", pFcbTable ); return; } dprintf( "\n FcbTable @ %08lx", (DWORD) pFcbTable ); dprintf( "\n FcbTable has %x elements", RtlNumberGenericTableElements( (PRTL_GENERIC_TABLE) &FcbTable ) ); RestartKey = NULL; for (pFcbTableElement = (PFCB_TABLE_ELEMENT) KdEnumerateGenericTableWithoutSplaying(pFcbTable, &RestartKey); pFcbTableElement != NULL; pFcbTableElement = (PFCB_TABLE_ELEMENT) KdEnumerateGenericTableWithoutSplaying(pFcbTable, &RestartKey)) { if ( !ReadMemory( (DWORD) pFcbTableElement, &FcbTableElement, sizeof( FcbTableElement ), &Result) ) { dprintf( "%08lx: Unable to read pFcbTableElement\n", pFcbTableElement ); return; } if (Options >= 2) { DumpFcb( (ULONG) FcbTableElement.Fcb, Options - 2 ); } else { dprintf( "\n Fcb @ %08lx for FileReference(%x,%x) ", (DWORD) FcbTableElement.Fcb, FcbTableElement.FileReference.SegmentNumberHighPart, FcbTableElement.FileReference.SegmentNumberLowPart ); } } } dprintf( "\n" ); return; }
/* * @implemented */ BOOLEAN NTAPI FsRtlPrivateLock(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp OPTIONAL, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized) { NTSTATUS Status; COMBINED_LOCK_ELEMENT ToInsert; PCOMBINED_LOCK_ELEMENT Conflict; PLOCK_INFORMATION LockInfo; PLOCK_SHARED_RANGE NewSharedRange; BOOLEAN InsertedNew; ULARGE_INTEGER UnsignedStart; ULARGE_INTEGER UnsignedEnd; DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n", &FileObject->FileName, FileOffset->HighPart, FileOffset->LowPart, (int)FileOffset->QuadPart, Length->HighPart, Length->LowPart, (int)Length->QuadPart, Key, FailImmediately, ExclusiveLock); UnsignedStart.QuadPart = FileOffset->QuadPart; UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart; if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart) { DPRINT("File offset out of range\n"); IoStatus->Status = STATUS_INVALID_PARAMETER; if (Irp) { DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } /* Initialize the lock, if necessary */ if (!FileLock->LockInformation) { LockInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOCK_INFORMATION), TAG_FLOCK); if (!LockInfo) { IoStatus->Status = STATUS_NO_MEMORY; return FALSE; } FileLock->LockInformation = LockInfo; LockInfo->BelongsTo = FileLock; InitializeListHead(&LockInfo->SharedLocks); RtlInitializeGenericTable (&LockInfo->RangeTable, LockCompare, LockAllocate, LockFree, NULL); KeInitializeSpinLock(&LockInfo->CsqLock); InitializeListHead(&LockInfo->CsqList); IoCsqInitializeEx (&LockInfo->Csq, LockInsertIrpEx, LockRemoveIrp, LockPeekNextIrp, LockAcquireQueueLock, LockReleaseQueueLock, LockCompleteCanceledIrp); } LockInfo = FileLock->LockInformation; ToInsert.Exclusive.FileLock.FileObject = FileObject; ToInsert.Exclusive.FileLock.StartingByte = *FileOffset; ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart; ToInsert.Exclusive.FileLock.ProcessId = Process->UniqueProcessId; ToInsert.Exclusive.FileLock.Key = Key; ToInsert.Exclusive.FileLock.ExclusiveLock = ExclusiveLock; Conflict = RtlInsertElementGenericTable (FileLock->LockInformation, &ToInsert, sizeof(ToInsert), &InsertedNew); if (Conflict && !InsertedNew) { if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock) { DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n", Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart, Conflict->Exclusive.FileLock.ExclusiveLock, ExclusiveLock); if (FailImmediately) { DPRINT("STATUS_FILE_LOCK_CONFLICT\n"); IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; if (Irp) { DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n"); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } else { IoStatus->Status = STATUS_PENDING; if (Irp) { Irp->IoStatus.Information = LockInfo->Generation; IoMarkIrpPending(Irp); IoCsqInsertIrpEx (&LockInfo->Csq, Irp, NULL, NULL); } } return FALSE; } else { ULONG i; /* We know of at least one lock in range that's shared. We need to * find out if any more exist and any are exclusive. */ for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++) { Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i); /* The first argument will be inserted as a shared range */ if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual)) { if (Conflict->Exclusive.FileLock.ExclusiveLock) { /* Found an exclusive match */ if (FailImmediately) { IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; DPRINT("STATUS_FILE_LOCK_CONFLICT\n"); if (Irp) { DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n"); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } } else { IoStatus->Status = STATUS_PENDING; if (Irp) { IoMarkIrpPending(Irp); IoCsqInsertIrpEx (&LockInfo->Csq, Irp, NULL, NULL); } } return FALSE; } } } DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart); Conflict = FsRtlpRebuildSharedLockRange(FileLock, LockInfo, &ToInsert); if (!Conflict) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } } /* We got here because there were only overlapping shared locks */ /* A shared lock is both a range *and* a list entry. Insert the entry here. */ DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange = ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE); if (!NewSharedRange) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange->Start = *FileOffset; NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart; NewSharedRange->Key = Key; NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId; InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry); DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart); IoStatus->Status = STATUS_SUCCESS; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return TRUE; } } else if (!Conflict) { /* Conflict here is (or would be) the newly inserted element, but we ran * out of space probably. */ IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } else { DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart, Conflict->Exclusive.FileLock.ExclusiveLock); if (!ExclusiveLock) { NewSharedRange = ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE); if (!NewSharedRange) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange->Start = *FileOffset; NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart; NewSharedRange->Key = Key; NewSharedRange->ProcessId = Process->UniqueProcessId; InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry); } /* Assume all is cool, and lock is set */ IoStatus->Status = STATUS_SUCCESS; if (Irp) { /* Complete the request */ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); /* Update the status */ IoStatus->Status = Status; } } return TRUE; }