Пример #1
0
VOID KphpTestPushLockThreadStart(
    __in PVOID Context
    )
{
    ULONG i, j;
    
    for (i = 0; i < 400000; i++)
    {
        ExAcquirePushLockShared(&TestLock);
        
        for (j = 0; j < 1000; j++)
            YieldProcessor();
        
        ExReleasePushLock(&TestLock);
        
        ExAcquirePushLockExclusive(&TestLock);
        
        for (j = 0; j < 9000; j++)
            YieldProcessor();
        
        ExReleasePushLock(&TestLock);
    }
    
    PsTerminateSystemThread(STATUS_SUCCESS);
}
Пример #2
0
NTSTATUS
NTAPI
CmpDestroyHive(IN PCMHIVE CmHive)
{
    /* Remove the hive from the list */
    ExAcquirePushLockExclusive(&CmpHiveListHeadLock);
    RemoveEntryList(&CmHive->HiveList);
    ExReleasePushLock(&CmpHiveListHeadLock);

    /* Delete the flusher lock */
    ExDeleteResourceLite(CmHive->FlusherLock);
    ExFreePoolWithTag(CmHive->FlusherLock, TAG_CMHIVE);

    /* Delete the view lock */
    ExFreePoolWithTag(CmHive->ViewLock, TAG_CMHIVE);

    /* Destroy the security descriptor cache */
    CmpDestroySecurityCache(CmHive);

    /* Destroy the view list */
    CmpDestroyHiveViewList(CmHive);

    /* Free the hive storage */
    HvFree(&CmHive->Hive);

    /* Free the hive */
    CmpFree(CmHive, TAG_CM);

    return STATUS_SUCCESS;
}
Пример #3
0
FORCEINLINE
VOID
ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry)
{
    /* Release the lock */
    ExReleasePushLock(&CacheEntry->PushLock);
    KeLeaveCriticalRegion();
}
Пример #4
0
NTSTATUS
NTAPI
CmpInitializeHive(OUT PCMHIVE *RegistryHive,
                  IN ULONG OperationType,
                  IN ULONG HiveFlags,
                  IN ULONG FileType,
                  IN PVOID HiveData OPTIONAL,
                  IN HANDLE Primary,
                  IN HANDLE Log,
                  IN HANDLE External,
                  IN PCUNICODE_STRING FileName OPTIONAL,
                  IN ULONG CheckFlags)
{
    PCMHIVE Hive;
    FILE_STANDARD_INFORMATION FileInformation;
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_FS_SIZE_INFORMATION FileSizeInformation;
    NTSTATUS Status;
    ULONG Cluster;

    /* Assume failure */
    *RegistryHive = NULL;

    /*
     * The following are invalid:
     * An external hive that is also internal.
     * A log hive that's not a primary hive too.
     * A volatile hive that's linked to permanent storage.
     * An in-memory initialization without hive data.
     * A log hive that's not linked to a correct file type.
     */
    if (((External) && ((Primary) || (Log))) ||
        ((Log) && !(Primary)) ||
        ((HiveFlags & HIVE_VOLATILE) && ((Primary) || (External) || (Log))) ||
        ((OperationType == HINIT_MEMORY) && (!HiveData)) ||
        ((Log) && (FileType != HFILE_TYPE_LOG)))
    {
        /* Fail the request */
        return STATUS_INVALID_PARAMETER;
    }

    /* Check if this is a primary hive */
    if (Primary)
    {
        /* Get the cluster size */
        Status = ZwQueryVolumeInformationFile(Primary,
                                              &IoStatusBlock,
                                              &FileSizeInformation,
                                              sizeof(FILE_FS_SIZE_INFORMATION),
                                              FileFsSizeInformation);
        if (!NT_SUCCESS(Status)) return Status;

        /* Make sure it's not larger then the block size */
        if (FileSizeInformation.BytesPerSector > HBLOCK_SIZE)
        {
            /* Fail */
            return STATUS_REGISTRY_IO_FAILED;
        }

        /* Otherwise, calculate the cluster */
        Cluster = FileSizeInformation.BytesPerSector / HSECTOR_SIZE;
        Cluster = max(1, Cluster);
    }
    else
    {
        /* Otherwise use cluster 1 */
        Cluster = 1;
    }

    /* Allocate the hive */
    Hive = ExAllocatePoolWithTag(NonPagedPool, sizeof(CMHIVE), TAG_CMHIVE);
    if (!Hive) return STATUS_INSUFFICIENT_RESOURCES;

    /* Setup null fields */
    Hive->UnloadEvent = NULL;
    Hive->RootKcb = NULL;
    Hive->Frozen = FALSE;
    Hive->UnloadWorkItem = NULL;
    Hive->GrowOnlyMode = FALSE;
    Hive->GrowOffset = 0;
    Hive->CellRemapArray = NULL;
    Hive->UseCountLog.Next = 0;
    Hive->LockHiveLog.Next = 0;
    Hive->FileObject = NULL;
    Hive->NotifyList.Flink = NULL;
    Hive->NotifyList.Blink = NULL;

    /* Set loading flag */
    Hive->HiveIsLoading = TRUE;

    /* Set the current thread as creator */
    Hive->CreatorOwner = KeGetCurrentThread();

    /* Initialize lists */
    InitializeListHead(&Hive->KcbConvertListHead);
    InitializeListHead(&Hive->KnodeConvertListHead);
    InitializeListHead(&Hive->TrustClassEntry);

    /* Allocate the view log */
    Hive->ViewLock = ExAllocatePoolWithTag(NonPagedPool,
                                           sizeof(KGUARDED_MUTEX),
                                           TAG_CMHIVE);
    if (!Hive->ViewLock)
    {
        /* Cleanup allocation and fail */
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Allocate the flush lock */
    Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool,
                                              sizeof(ERESOURCE),
                                              TAG_CMHIVE);
    if (!Hive->FlusherLock)
    {
        /* Cleanup allocations and fail */
        ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Setup the handles */
    Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
    Hive->FileHandles[HFILE_TYPE_LOG] = Log;
    Hive->FileHandles[HFILE_TYPE_EXTERNAL] = External;

    /* Initailize the guarded mutex */
    KeInitializeGuardedMutex(Hive->ViewLock);
    Hive->ViewLockOwner = NULL;

    /* Initialize the flush lock */
    ExInitializeResourceLite(Hive->FlusherLock);

    /* Setup hive locks */
    ExInitializePushLock(&Hive->HiveLock);
    Hive->HiveLockOwner = NULL;
    ExInitializePushLock(&Hive->WriterLock);
    Hive->WriterLockOwner = NULL;
    ExInitializePushLock(&Hive->SecurityLock);
    Hive->HiveSecurityLockOwner = NULL;

    /* Clear file names */
    RtlInitEmptyUnicodeString(&Hive->FileUserName, NULL, 0);
    RtlInitEmptyUnicodeString(&Hive->FileFullPath, NULL, 0);

    /* Initialize the view list */
    CmpInitHiveViewList(Hive);

    /* Initailize the security cache */
    CmpInitSecurityCache(Hive);

    /* Setup flags */
    Hive->Flags = 0;
    Hive->FlushCount = 0;

    /* Set flags */
    Hive->Flags = HiveFlags;

    /* Check if this is a primary */
    if (Primary)
    {
        /* Check how large the file is */
        ZwQueryInformationFile(Primary,
                               &IoStatusBlock,
                               &FileInformation,
                               sizeof(FileInformation),
                               FileStandardInformation);
        Cluster = FileInformation.EndOfFile.LowPart;
    }

    /* Initialize it */
    Status = HvInitialize(&Hive->Hive,
                          OperationType,
                          FileType,
                          HiveFlags,
                          HiveData,
                          CmpAllocate,
                          CmpFree,
                          CmpFileSetSize,
                          CmpFileWrite,
                          CmpFileRead,
                          CmpFileFlush,
                          Cluster,
                          FileName);
    if (!NT_SUCCESS(Status))
    {
        /* Cleanup allocations and fail */
        ExDeleteResourceLite(Hive->FlusherLock);
        ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return Status;
    }

    /* Check if we should verify the registry */
    if ((OperationType == HINIT_FILE) ||
        (OperationType == HINIT_MEMORY) ||
        (OperationType == HINIT_MEMORY_INPLACE) ||
        (OperationType == HINIT_MAPFILE))
    {
        /* Verify integrity */
        ULONG CheckStatus = CmCheckRegistry(Hive, CheckFlags);
        if (CheckStatus != 0)
        {
            /* Cleanup allocations and fail */
            ExDeleteResourceLite(Hive->FlusherLock);
            ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE);
            ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
            ExFreePoolWithTag(Hive, TAG_CMHIVE);
            return STATUS_REGISTRY_CORRUPT;
        }
    }

    /* Lock the hive list */
    ExAcquirePushLockExclusive(&CmpHiveListHeadLock);

    /* Insert this hive */
    InsertHeadList(&CmpHiveListHead, &Hive->HiveList);

    /* Release the lock */
    ExReleasePushLock(&CmpHiveListHeadLock);

    /* Return the hive and success */
    *RegistryHive = (PCMHIVE)Hive;
    return STATUS_SUCCESS;
}
Пример #5
0
BOOLEAN
NTAPI
CmpDoFlushNextHive(_In_  BOOLEAN ForceFlush,
                   _Out_ PBOOLEAN Error,
                   _Out_ PULONG DirtyCount)
{
    NTSTATUS Status;
    PLIST_ENTRY NextEntry;
    PCMHIVE CmHive;
    BOOLEAN Result;
    ULONG HiveCount = CmpLazyFlushHiveCount;

    /* Set Defaults */
    *Error = FALSE;
    *DirtyCount = 0;

    /* Don't do anything if we're not supposed to */
    if (CmpNoWrite) return TRUE;

    /* Make sure we have to flush at least one hive */
    if (!HiveCount) HiveCount = 1;

    /* Acquire the list lock and loop */
    ExAcquirePushLockShared(&CmpHiveListHeadLock);
    NextEntry = CmpHiveListHead.Flink;
    while ((NextEntry != &CmpHiveListHead) && HiveCount)
    {
        /* Get the hive and check if we should flush it */
        CmHive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList);
        if (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH) &&
            (CmHive->FlushCount != CmpLazyFlushCount))
        {
            /* Great sucess! */
            Result = TRUE;

            /* One less to flush */
            HiveCount--;

            /* Ignore clean or volatile hives */
            if ((!CmHive->Hive.DirtyCount && !ForceFlush) ||
                (CmHive->Hive.HiveFlags & HIVE_VOLATILE))
            {
                /* Don't do anything but do update the count */
                CmHive->FlushCount = CmpLazyFlushCount;
                DPRINT("Hive %wZ is clean.\n", &CmHive->FileFullPath);
            }
            else
            {
                /* Do the sync */
                DPRINT("Flushing: %wZ\n", &CmHive->FileFullPath);
                DPRINT("Handle: %p\n", CmHive->FileHandles[HFILE_TYPE_PRIMARY]);
                Status = HvSyncHive(&CmHive->Hive);
                if(!NT_SUCCESS(Status))
                {
                    /* Let them know we failed */
                    DPRINT1("Failed to flush %wZ on handle %p (status 0x%08lx)\n",
                        &CmHive->FileFullPath,  CmHive->FileHandles[HFILE_TYPE_PRIMARY], Status);
                    *Error = TRUE;
                    Result = FALSE;
                    break;
                }
                CmHive->FlushCount = CmpLazyFlushCount;
            }
        }
        else if ((CmHive->Hive.DirtyCount) &&
                 (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) &&
                 (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH)))
        {
            /* Use another lazy flusher for this hive */
            ASSERT(CmHive->FlushCount == CmpLazyFlushCount);
            *DirtyCount += CmHive->Hive.DirtyCount;
            DPRINT("CmHive %wZ already uptodate.\n", &CmHive->FileFullPath);
        }

        /* Try the next one */
        NextEntry = NextEntry->Flink;
    }

    /* Check if we've flushed everything */
    if (NextEntry == &CmpHiveListHead)
    {
        /* We have, tell the caller we're done */
        Result = FALSE;
    }
    else
    {
        /* We need to be called again */
        Result = TRUE;
    }

    /* Unlock the list and return the result */
    ExReleasePushLock(&CmpHiveListHeadLock);
    return Result;
}