示例#1
0
VOID
NTAPI
CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    ULONG i;
    PCM_ALLOC_PAGE AllocPage;
    PAGED_CODE();
    
    /* Sanity checks */
    ASSERT(IsListEmpty(&Kcb->KeyBodyListHead) == TRUE);
    for (i = 0; i < 4; i++) ASSERT(Kcb->KeyBodyArray[i] == NULL);
    
    /* Check if it wasn't privately allocated */
    if (!Kcb->PrivateAlloc)
    {
        /* Free it from the pool */
        CmpFree(Kcb, 0);
        return;
    }
    
    /* Acquire the private allocation lock */
    KeAcquireGuardedMutex(&CmpAllocBucketLock);
    
    /* Sanity check on lock ownership */
    CMP_ASSERT_HASH_ENTRY_LOCK(Kcb->ConvKey);
    
    /* Add us to the free list */
    InsertTailList(&CmpFreeKCBListHead, &Kcb->FreeListEntry);
    
    /* Get the allocation page */
    AllocPage = CmpGetAllocPageFromKcb(Kcb);
    
    /* Sanity check */
    ASSERT(AllocPage->FreeCount != CM_KCBS_PER_PAGE);
    
    /* Increase free count */
    if (++AllocPage->FreeCount == CM_KCBS_PER_PAGE)
    {
        /* Loop all the entries */
        for (i = 0; i < CM_KCBS_PER_PAGE; i++)
        {
            /* Get the KCB */
            Kcb = (PVOID)((ULONG_PTR)AllocPage +
                          FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
                          i * sizeof(CM_KEY_CONTROL_BLOCK));
            
            /* Remove the entry */ 
            RemoveEntryList(&Kcb->FreeListEntry);
        }
        
        /* Free the page */
        CmpFree(AllocPage, 0);
    }
    
    /* Release the lock */
    KeReleaseGuardedMutex(&CmpAllocBucketLock);
}
示例#2
0
文件: cminit.c 项目: Strongc/reactos
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
VOID
NTAPI
CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    PULONG_PTR CachedList;
    ULONG i;

    /* Sanity check */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Check if the value list is cached */
    if (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
    {
        /* Get the cache list */
        CachedList = (PULONG_PTR)CMP_GET_CACHED_DATA(Kcb->ValueCache.ValueList);
        for (i = 0; i < Kcb->ValueCache.Count; i++)
        {
            /* Check if this cell is cached */
            if (CMP_IS_CELL_CACHED(CachedList[i]))
            {
                /* Free it */
                CmpFree((PVOID)CMP_GET_CACHED_CELL(CachedList[i]), 0);
            }
        }

        /* Now free the list */
        CmpFree((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList), 0);
        Kcb->ValueCache.ValueList = HCELL_NIL;
    }
    else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
    {
        /* This is a sym link, check if there's only one reference left */
        if ((Kcb->ValueCache.RealKcb->RefCount == 1) &&
                !(Kcb->ValueCache.RealKcb->Delete))
        {
            /* Disable delay close for the KCB */
            Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
        }

        /* Dereference the KCB */
        CmpDelayDerefKeyControlBlock(Kcb->ValueCache.RealKcb);
        Kcb->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    }
}
示例#4
0
VOID
NTAPI
CmpCleanUpSubKeyInfo(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    PCM_KEY_NODE KeyNode;

    /* Sanity check */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Check if there's any cached subkey */
    if (Kcb->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT))
    {
        /* Check if there's a hint */
        if (Kcb->ExtFlags & (CM_KCB_SUBKEY_HINT))
        {
            /* Kill it */
            CmpFree(Kcb->IndexHint, 0);
        }

        /* Remove subkey flags */
        Kcb->ExtFlags &= ~(CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT);
    }

    /* Check if there's no linked cell */
    if (Kcb->KeyCell == HCELL_NIL)
    {
        /* Make sure it's a delete */
        ASSERT(Kcb->Delete);
        KeyNode = NULL;
    }
    else
    {
        /* Get the key node */
        KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
    }

    /* Check if we got the node */
    if (!KeyNode)
    {
        /* We didn't, mark the cached data invalid */
        Kcb->ExtFlags |= CM_KCB_INVALID_CACHED_INFO;
    }
    else
    {
        /* We have a keynode, update subkey counts */
        Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
        Kcb->SubKeyCount = KeyNode->SubKeyCounts[Stable] +
                           KeyNode->SubKeyCounts[Volatile];

        /* Release the cell */
        HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
    }
}
示例#5
0
VOID
NTAPI
CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
                           IN BOOLEAN LockHeldExclusively)
{
    PCM_KEY_CONTROL_BLOCK Parent;
    PAGED_CODE();

    /* Sanity checks */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));
    ASSERT(Kcb->RefCount == 0);

    /* Cleanup the value cache */
    CmpCleanUpKcbValueCache(Kcb);

    /* Dereference the NCB */
    CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);

    /* Check if we have an index hint block and free it */
    if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) CmpFree(Kcb->IndexHint, 0);

    /* Check if we were already deleted */
    Parent = Kcb->ParentKcb;
    if (!Kcb->Delete) CmpRemoveKeyControlBlock(Kcb);

    /* Set invalid KCB signature */
    Kcb->Signature = CM_KCB_INVALID_SIGNATURE;

    /* Free the KCB as well */
    CmpFreeKeyControlBlock(Kcb);

    /* Check if we have a parent */
    if (Parent)
    {
        /* Dereference the parent */
        LockHeldExclusively ?
        CmpDereferenceKeyControlBlockWithLock(Parent,LockHeldExclusively) :
        CmpDelayDerefKeyControlBlock(Parent);
    }
}
示例#6
0
VOID
NTAPI
CmpFreeDelayItem(PVOID Entry)
{
    PCM_DELAY_ALLOC AllocEntry = (PCM_DELAY_ALLOC)Entry;
    PCM_ALLOC_PAGE AllocPage;
    ULONG i;
    PAGED_CODE();
    
    /* Lock the table */
    KeAcquireGuardedMutex(&CmpDelayAllocBucketLock);
    
    /* Add the entry at the end */
    InsertTailList(&CmpFreeDelayItemsListHead, &AllocEntry->ListEntry);
    
    /* Get the alloc page */
    AllocPage = CmpGetAllocPageFromDelayAlloc(Entry);
    ASSERT(AllocPage->FreeCount != CM_DELAYS_PER_PAGE);
    
    /* Increase the number of free items */
    if (++AllocPage->FreeCount == CM_DELAYS_PER_PAGE)
    {
        /* Page is totally free now, loop each entry */
        for (i = 0; i < CM_DELAYS_PER_PAGE; i++)
        {
            /* Get the entry and unlink it */
            AllocEntry = (PVOID)((ULONG_PTR)AllocPage +
                                 FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
                                 i * sizeof(CM_DELAY_ALLOC));
            RemoveEntryList(&AllocEntry->ListEntry);
        }
        
        /* Now free the page */
        CmpFree(AllocPage, 0);
    }
    
    /* Release the lock */
    KeReleaseGuardedMutex(&CmpDelayAllocBucketLock);
}
示例#7
0
VOID
NTAPI
CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
{
    PCM_NAME_HASH Current, *Next;
    ULONG ConvKey = Ncb->ConvKey;

    /* Lock the NCB */
    CmpAcquireNcbLockExclusiveByKey(ConvKey);

    /* Decrease the reference count */
    ASSERT(Ncb->RefCount >= 1);
    if (!(--Ncb->RefCount))
    {
        /* Find the NCB in the table */
        Next = &GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey).Entry;
        while (TRUE)
        {
            /* Check the current entry */
            Current = *Next;
            ASSERT(Current != NULL);
            if (Current == &Ncb->NameHash)
            {
                /* Unlink it */
                *Next = Current->NextHash;
                break;
            }

            /* Get to the next one */
            Next = &Current->NextHash;
        }

        /* Found it, now free it */
        CmpFree(Ncb, 0);
    }

    /* Release the lock */
    CmpReleaseNcbLockByKey(ConvKey);
}
示例#8
0
VALUE_SEARCH_RETURN_TYPE
NTAPI
CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
                                      IN PUNICODE_STRING ValueName,
                                      IN ULONG Type,
                                      IN PVOID Data,
                                      IN ULONG DataSize)
{
    VALUE_SEARCH_RETURN_TYPE SearchResult;
    PCM_KEY_NODE KeyNode;
    PCM_CACHED_VALUE *CachedValue;
    ULONG Index;
    PCM_KEY_VALUE Value;
    BOOLEAN ValueCached, BufferAllocated = FALSE;
    PVOID Buffer;
    HCELL_INDEX ValueCellToRelease = HCELL_NIL, CellToRelease = HCELL_NIL;
    BOOLEAN IsSmall;
    ULONG CompareResult;
    PAGED_CODE();

    /* Check if this is a symlink */
    if (Kcb->Flags & KEY_SYM_LINK)
    {
        /* We need the exclusive lock */
        if (!(CmpIsKcbLockedExclusive(Kcb)) &&
            !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
        {
            /* We need the exclusive lock */
            return SearchNeedExclusiveLock;
        }
        
        /* Otherwise, get the key node */
        KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
        if (!KeyNode) return SearchFail;
        
        /* Cleanup the KCB cache */
        CmpCleanUpKcbValueCache(Kcb);
        
        /* Sanity checks */
        ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
        ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
        
        /* Set the value cache */
        Kcb->ValueCache.Count = KeyNode->ValueList.Count;
        Kcb->ValueCache.ValueList = KeyNode->ValueList.List;
        
        /* Release the cell */
        HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
    }
    
    /* Do the search */
    SearchResult = CmpFindValueByNameFromCache(Kcb,
                                               ValueName,
                                               &CachedValue,
                                               &Index,
                                               &Value,
                                               &ValueCached,
                                               &ValueCellToRelease);
    if (SearchResult == SearchNeedExclusiveLock)
    {
        /* We need the exclusive lock */
        ASSERT(!CmpIsKcbLockedExclusive(Kcb));
        ASSERT(ValueCellToRelease == HCELL_NIL);
        ASSERT(Value == NULL);
        goto Quickie;
    }
    else if (SearchResult == SearchSuccess)
    {
        /* Sanity check */
        ASSERT(Value);
        
        /* First of all, check if the key size and type matches */
        if ((Type == Value->Type) &&
            (DataSize == (Value->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE)))
        {
            /* Check if this is a small key */
            IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
            if (IsSmall)
            {
                /* Compare against the data directly */
                Buffer = &Value->Data;
            }
            else
            {
                /* Do a search */
                SearchResult = CmpGetValueDataFromCache(Kcb,
                                                        CachedValue,
                                                        (PCELL_DATA)Value,
                                                        ValueCached,
                                                        &Buffer,
                                                        &BufferAllocated,
                                                        &CellToRelease);
                if (SearchResult != SearchSuccess)
                {
                    /* Sanity checks */
                    ASSERT(Buffer == NULL);
                    ASSERT(BufferAllocated == FALSE);
                    goto Quickie;
                }
            }
            
            /* Now check the data size */
            if (DataSize)
            {
                /* Do the compare */
                CompareResult = RtlCompareMemory(Buffer,
                                                 Data,
                                                 DataSize &
                                                 ~CM_KEY_VALUE_SPECIAL_SIZE);
            }
            else
            {
                /* It's equal */
                CompareResult = 0;
            }
            
            /* Now check if the compare wasn't equal */
            if (CompareResult != DataSize) SearchResult = SearchFail;
        }
        else
        {
            /* The length or type isn't equal */
            SearchResult = SearchFail;
        }
    }

Quickie:
    /* Release the value cell */
    if (ValueCellToRelease) HvReleaseCell(Kcb->KeyHive, ValueCellToRelease);
    
    /* Free the buffer */
    if (BufferAllocated) CmpFree(Buffer, 0);
    
    /* Free the cell */
    if (CellToRelease) HvReleaseCell(Kcb->KeyHive, CellToRelease);

    /* Return the search result */
    return SearchResult;
}
示例#9
0
VOID
HvFreeHive(
    PHHIVE Hive
    )
/*++

Routine Description:

    Free all of the pieces of a hive.

Arguments:

    Hive - supplies a pointer to hive control structure for hive to free.
            this structure itself will NOT be freed, but everything it
            points to will.

Return Value:

    NONE.

--*/
{
    PHMAP_DIRECTORY Dir;
    PHMAP_ENTRY     Me;
    HCELL_INDEX     Address;
    ULONG           Type;
    ULONG           Length;
    PHBIN           Bin;
    ULONG           Tables;
    PFREE_HBIN      FreeBin;

    ASSERT(Hive->Flat == FALSE);
    ASSERT(Hive->ReadOnly == FALSE);
    ASSERT(Stable == 0);
    ASSERT(Volatile == 1);

    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive(%ws) :\n", Hive->BaseBlock->FileName));
    //
    // Iterate through both types of storage
    //
    for (Type = 0; Type <= Volatile; Type++) {

        Address = HCELL_TYPE_MASK * Type;
        Length = Hive->Storage[Type].Length + (HCELL_TYPE_MASK * Type);

        if( Hive->Storage[Type].Map && (Length > (HCELL_TYPE_MASK * Type)) ) {

            //
            // Sweep through bin set
            //
            do {
                Me = HvpGetCellMap(Hive, Address);
                VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address);
                    if (Me->BinAddress & HMAP_DISCARDABLE) {
                        //
                        // hbin is either discarded or discardable, check the tombstone
                        //
                        FreeBin = (PFREE_HBIN)Me->BlockAddress;
                        Address += FreeBin->Size;
                        if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
                            CmpFree((PHBIN)HBIN_BASE(Me->BinAddress), FreeBin->Size);
                        } else if(Me->BinAddress & HMAP_INPAGEDPOOL) {
                            //
                            // The bin has been freed, but quota is still charged.
                            // Since the hive is being freed, the quota must be
                            // returned here.
                            //
                            CmpReleaseGlobalQuota(FreeBin->Size);
                        }

                        CmpFree(FreeBin, sizeof(FREE_HBIN));
                    } else {
                        if( Me->BinAddress & HMAP_INPAGEDPOOL ) {
                            ASSERT( Me->BinAddress & HMAP_INPAGEDPOOL );

                            Bin = (PHBIN)HBIN_BASE(Me->BinAddress);
                            Address += HvpGetBinMemAlloc(Hive,Bin,Type);
#if DBG
                            if( Type == Stable ) {
                                CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive: BinAddress = 0x%p\t Size = 0x%lx\n", Bin, HvpGetBinMemAlloc(Hive,Bin,Type)));
                            }
#endif

                            //
                            // free the actual bin only if it is allocated from paged pool
                            //
                            if(HvpGetBinMemAlloc(Hive,Bin,Type)) {
                                CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type));
                            }
                        } else {
                            //
                            // bin was mapped into view; advance carefully
                            //
                            Address += HBLOCK_SIZE;
                        }

                    }
            } while (Address < Length);

            //
            // Free map table storage
            //
            ASSERT(Hive->Storage[Type].Length != (HCELL_TYPE_MASK * Type));
            Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE)-1) / HTABLE_SLOTS;
            Dir = Hive->Storage[Type].Map;
            HvpFreeMap(Hive, Dir, 0, Tables);

            if (Tables > 0) {
                CmpFree(Hive->Storage[Type].Map, sizeof(HMAP_DIRECTORY));  // free dir if it exists
            }
        }
        Hive->Storage[Type].Length = 0;
    }

    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n"));
    //
    // Free the base block
    //
    (Hive->Free)(Hive->BaseBlock,Hive->BaseBlockAlloc);
    Hive->BaseBlock = NULL;
    
    //
    // Free the dirty vector
    //
    if (Hive->DirtyVector.Buffer != NULL) {
        CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc);
    }

    HvpFreeHiveFreeDisplay(Hive);
    LogHiveFree(Hive);
    return;
}
示例#10
0
VOID
HvFreeHivePartial(
    PHHIVE      Hive,
    HCELL_INDEX Start,
    HSTORAGE_TYPE Type
    )
/*++

Routine Description:

    Free the memory and associated maps for the end of a hive
    starting at Start.  The baseblock, hive, etc will not be touched.

Arguments:

    Hive - supplies a pointer to hive control structure for hive to
            partially free.

    Start - HCELL_INDEX of first bin to free, will free from this
            bin (inclusive) to the end of the hives stable storage.

    Type - Type of storage (Stable or Volatile) to be freed.

Return Value:

    NONE.

--*/
{
    PHMAP_DIRECTORY Dir;
    PHMAP_ENTRY     Me;
    HCELL_INDEX     Address;
    ULONG           StartTable;
    ULONG           Length;
    PHBIN           Bin;
    ULONG           Tables;
    ULONG           FirstBit;
    ULONG           LastBit;
    PFREE_HBIN      FreeBin;

    ASSERT(Hive->Flat == FALSE);
    ASSERT(Hive->ReadOnly == FALSE);

    Address = Start;
    Length = Hive->Storage[Type].Length;
    ASSERT(Address <= Length);

    if (Address == Length) {
        return;
    }

    //
    // Sweep through bin set
    //
    do {
        Me = HvpGetCellMap(Hive, Address + (Type*HCELL_TYPE_MASK));
        VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address + (Type*HCELL_TYPE_MASK));
        if (Me->BinAddress & HMAP_DISCARDABLE) {
            FreeBin = (PFREE_HBIN)Me->BlockAddress;
            if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
                CmpFree((PVOID)HBIN_BASE(Me->BinAddress), FreeBin->Size);
            } else {
                //
                // The bin has been freed, but quota is still charged.
                // Since the file will now shrink, the quota must be
                // returned here.
                //
                if( Me->BinAddress & HMAP_INPAGEDPOOL) {
                    //
                    // we charge quota only for bins in paged-pool
                    //
                    CmpReleaseGlobalQuota(FreeBin->Size);
                }
            }
            RemoveEntryList(&FreeBin->ListEntry);
            Address += FreeBin->Size;
            CmpFree(FreeBin, sizeof(FREE_HBIN));

        } else {
            Bin = (PHBIN)HBIN_BASE(Me->BinAddress);
            Address += HvpGetBinMemAlloc(Hive,Bin,Type);
            
            if( Me->BinAddress & HMAP_INPAGEDPOOL && HvpGetBinMemAlloc(Hive,Bin,Type) ) {
                //
                // free the bin only if it is allocated from paged pool
                //
                CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type));
            }
        }
    } while (Address < Length);

    //
    // Free map table storage
    //
    Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE) - 1) / HTABLE_SLOTS;
    Dir = Hive->Storage[Type].Map;
    if (Start > 0) {
        StartTable = ((Start-1) / HBLOCK_SIZE) / HTABLE_SLOTS;
    } else {
        StartTable = (ULONG)-1;
    }
    HvpFreeMap(Hive, Dir, StartTable+1, Tables);

    //
    // update hysteresis (eventually queue work item)
    //
    if( Type == Stable) {
        CmpUpdateSystemHiveHysteresis(Hive,(Start&(~HCELL_TYPE_MASK)),Hive->Storage[Type].Length);
    }

    Hive->Storage[Type].Length = (Start&(~HCELL_TYPE_MASK));

    if (Type==Stable) {
        //
        // Clear dirty vector for data past Hive->Storage[Stable].Length
        //
        FirstBit = Start / HSECTOR_SIZE;
        LastBit = Hive->DirtyVector.SizeOfBitMap;
        ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector));
        RtlClearBits(&Hive->DirtyVector, FirstBit, LastBit-FirstBit);
        Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector);
    }

    HvpAdjustHiveFreeDisplay(Hive,Hive->Storage[Type].Length,Type);

    return;
}
示例#11
0
BOOLEAN
RegImportBinaryHive(
    PCHAR ChunkBase,
    ULONG ChunkSize)
{
    PCM_KEY_NODE KeyCell;
    PCM_KEY_FAST_INDEX HashCell;
    PCM_KEY_NODE SubKeyCell;
    FRLDRHKEY SystemKey;
    ULONG i;
    LONG Error;
    PCMHIVE CmHive;
    PHHIVE Hive;
    NTSTATUS Status;

    TRACE("RegImportBinaryHive(%x, %u) called\n", ChunkBase, ChunkSize);

    CmHive = CmpAllocate(sizeof(CMHIVE), TRUE, 0);
    Status = HvInitialize(&CmHive->Hive,
                          HINIT_FLAT,
                          0,
                          0,
                          ChunkBase,
                          CmpAllocate,
                          CmpFree,
                          NULL,
                          NULL,
                          NULL,
                          NULL,
                          1,
                          NULL);
    if (!NT_SUCCESS(Status))
    {
        CmpFree(CmHive, 0);
        ERR("Invalid hive Signature!\n");
        return FALSE;
    }

    Hive = &CmHive->Hive;
    KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, Hive->BaseBlock->RootCell);
    TRACE("KeyCell: %x\n", KeyCell);
    TRACE("KeyCell->Signature: %x\n", KeyCell->Signature);
    if (KeyCell->Signature != CM_KEY_NODE_SIGNATURE)
    {
        ERR("Invalid key cell Signature!\n");
        return FALSE;
    }

    TRACE("Subkeys: %u\n", KeyCell->SubKeyCounts);
    TRACE("Values: %u\n", KeyCell->ValueList.Count);

    /* Open 'System' key */
    Error = RegOpenKey(NULL, L"\\Registry\\Machine\\SYSTEM", &SystemKey);
    if (Error != ERROR_SUCCESS)
    {
        ERR("Failed to open 'system' key!\n");
        return FALSE;
    }

    /* Enumerate and add subkeys */
    if (KeyCell->SubKeyCounts[Stable] > 0)
    {
        HashCell = (PCM_KEY_FAST_INDEX)HvGetCell(Hive, KeyCell->SubKeyLists[Stable]);
        TRACE("HashCell: %x\n", HashCell);
        TRACE("SubKeyCounts: %x\n", KeyCell->SubKeyCounts[Stable]);

        for (i = 0; i < KeyCell->SubKeyCounts[Stable]; i++)
        {
            TRACE("Cell[%d]: %x\n", i, HashCell->List[i].Cell);

            SubKeyCell = (PCM_KEY_NODE)HvGetCell(Hive, HashCell->List[i].Cell);

            TRACE("SubKeyCell[%d]: %x\n", i, SubKeyCell);

            if (!RegImportSubKey(Hive, SubKeyCell, SystemKey))
                return FALSE;
        }
    }

    return TRUE;
}
示例#12
0
PUNICODE_STRING
NTAPI
CmpConstructName(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    PUNICODE_STRING KeyName;
    ULONG NameLength, i;
    PCM_KEY_CONTROL_BLOCK MyKcb;
    PCM_KEY_NODE KeyNode;
    BOOLEAN DeletedKey = FALSE;
    PWCHAR TargetBuffer, CurrentNameW;
    PUCHAR CurrentName;

    /* Calculate how much size our key name is going to occupy */
    NameLength = 0;
    MyKcb = Kcb;

    while (MyKcb)
    {
        /* Add length of the name */
        if (!MyKcb->NameBlock->Compressed)
        {
            NameLength += MyKcb->NameBlock->NameLength;
        }
        else
        {
            NameLength += CmpCompressedNameSize(MyKcb->NameBlock->Name,
                                                MyKcb->NameBlock->NameLength);
        }

        /* Sum up the separator too */
        NameLength += sizeof(WCHAR);

        /* Go to the parent KCB */
        MyKcb = MyKcb->ParentKcb;
    }

    /* Allocate the unicode string now */
    KeyName = CmpAllocate(NameLength + sizeof(UNICODE_STRING),
                          TRUE,
                          TAG_CM);

    if (!KeyName) return NULL;

    /* Set it up */
    KeyName->Buffer = (PWSTR)(KeyName + 1);
    KeyName->Length = NameLength;
    KeyName->MaximumLength = NameLength;

    /* Loop the keys again, now adding names */
    NameLength = 0;
    MyKcb = Kcb;

    while (MyKcb)
    {
        /* Sanity checks for deleted and fake keys */
        if ((!MyKcb->KeyCell && !MyKcb->Delete) ||
                !MyKcb->KeyHive ||
                MyKcb->ExtFlags & CM_KCB_KEY_NON_EXIST)
        {
            /* Failure */
            CmpFree(KeyName, 0);
            return NULL;
        }

        /* Try to get the name from the keynode,
           if the key is not deleted */
        if (!DeletedKey && !MyKcb->Delete)
        {
            KeyNode = HvGetCell(MyKcb->KeyHive, MyKcb->KeyCell);

            if (!KeyNode)
            {
                /* Failure */
                CmpFree(KeyName, 0);
                return NULL;
            }
        }
        else
        {
            /* The key was deleted */
            KeyNode = NULL;
            DeletedKey = TRUE;
        }

        /* Get the pointer to the beginning of the current key name */
        NameLength += (MyKcb->NameBlock->NameLength + 1) * sizeof(WCHAR);
        TargetBuffer = &KeyName->Buffer[(KeyName->Length - NameLength) / sizeof(WCHAR)];

        /* Add a separator */
        TargetBuffer[0] = OBJ_NAME_PATH_SEPARATOR;

        /* Add the name, but remember to go from the end to the beginning */
        if (!MyKcb->NameBlock->Compressed)
        {
            /* Get the pointer to the name (from the keynode, if possible) */
            if ((MyKcb->Flags & (KEY_HIVE_ENTRY | KEY_HIVE_EXIT)) ||
                    !KeyNode)
            {
                CurrentNameW = MyKcb->NameBlock->Name;
            }
            else
            {
                CurrentNameW = KeyNode->Name;
            }

            /* Copy the name */
            for (i=0; i < MyKcb->NameBlock->NameLength; i++)
            {
                TargetBuffer[i+1] = *CurrentNameW;
                CurrentNameW++;
            }
        }
        else
        {
            /* Get the pointer to the name (from the keynode, if possible) */
            if ((MyKcb->Flags & (KEY_HIVE_ENTRY | KEY_HIVE_EXIT)) ||
                    !KeyNode)
            {
                CurrentName = (PUCHAR)MyKcb->NameBlock->Name;
            }
            else
            {
                CurrentName = (PUCHAR)KeyNode->Name;
            }

            /* Copy the name */
            for (i=0; i < MyKcb->NameBlock->NameLength; i++)
            {
                TargetBuffer[i+1] = (WCHAR)*CurrentName;
                CurrentName++;
            }
        }

        /* Release the cell, if needed */
        if (KeyNode) HvReleaseCell(MyKcb->KeyHive, MyKcb->KeyCell);

        /* Go to the parent KCB */
        MyKcb = MyKcb->ParentKcb;
    }

    /* Return resulting buffer (both UNICODE_STRING and
       its buffer following it) */
    return KeyName;
}