Ejemplo n.º 1
0
/*
 * @implemented
 */
VOID
NTAPI
FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
{
    if (FileLock->LockInformation)
    {
        PIRP Irp;
        PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
        PCOMBINED_LOCK_ELEMENT Entry;
        PLIST_ENTRY SharedEntry;
        PLOCK_SHARED_RANGE SharedRange;
        // MSDN: this completes any remaining lock IRPs
        for (SharedEntry = InternalInfo->SharedLocks.Flink;
             SharedEntry != &InternalInfo->SharedLocks;)
        {
            SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
            SharedEntry = SharedEntry->Flink;
            RemoveEntryList(&SharedRange->Entry);
            ExFreePoolWithTag(SharedRange, TAG_RANGE);
        }
        while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
        {
            RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
        }
        while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
        {
            FsRtlProcessFileLock(FileLock, Irp, NULL);
        }
        ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
        FileLock->LockInformation = NULL;
    }
}
Ejemplo n.º 2
0
/*
 * @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;
}
Ejemplo n.º 3
0
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");
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
VOID
NTAPI
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment,
                               FREE_SECTION_PAGE_FUN FreePage)
{
    PCACHE_SECTION_PAGE_TABLE Element;
    DPRINT("MiFreePageTablesSectionSegment(%p)\n", &Segment->PageTable);
    while ((Element = RtlGetElementGenericTable(&Segment->PageTable, 0))) {
        DPRINT("Delete table for <%wZ> %p -> %I64x\n",
               Segment->FileObject ? &Segment->FileObject->FileName : NULL,
               Segment,
               Element->FileOffset.QuadPart);
        if (FreePage)
        {
            ULONG i;
            for (i = 0; i < ENTRIES_PER_ELEMENT; i++)
            {
                ULONG_PTR Entry;
                LARGE_INTEGER Offset;
                Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE;
                Entry = Element->PageEntries[i];
                if (Entry && !IS_SWAP_FROM_SSE(Entry))
                {
                    DPRINT("Freeing page %p:%Ix @ %I64x\n",
                           Segment,
                           Entry,
                           Offset.QuadPart);

                    FreePage(Segment, &Offset);
                }
            }
        }
        DPRINT("Remove memory\n");
        RtlDeleteElementGenericTable(&Segment->PageTable, Element);
    }
    DPRINT("Done\n");
}
Ejemplo n.º 6
0
/*
 * @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;
}