Пример #1
0
VOID
NTAPI
INIT_FUNCTION
CmpInitializeCache(VOID)
{
    ULONG Length, i;

    /* Calculate length for the table */
    Length = CmpHashTableSize * sizeof(CM_KEY_HASH_TABLE_ENTRY);

    /* Allocate it */
    CmpCacheTable = CmpAllocate(Length, TRUE, TAG_CM);
    if (!CmpCacheTable)
    {
        /* Take the system down */
        KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 1, 0, 0);
    }

    /* Zero out the table */
    RtlZeroMemory(CmpCacheTable, Length);

    /* Initialize the locks */
    for (i = 0; i < CmpHashTableSize; i++)
    {
        /* Setup the pushlock */
        ExInitializePushLock(&CmpCacheTable[i].Lock);
    }

    /* Calculate length for the name cache */
    Length = CmpHashTableSize * sizeof(CM_NAME_HASH_TABLE_ENTRY);

    /* Now allocate the name cache table */
    CmpNameCacheTable = CmpAllocate(Length, TRUE, TAG_CM);
    if (!CmpNameCacheTable)
    {
        /* Take the system down */
        KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 3, 3, 0, 0);
    }

    /* Zero out the table */
    RtlZeroMemory(CmpNameCacheTable, Length);

    /* Initialize the locks */
    for (i = 0; i < CmpHashTableSize; i++)
    {
        /* Setup the pushlock */
        ExInitializePushLock(&CmpNameCacheTable[i].Lock);
    }

    /* Setup the delayed close table */
    CmpInitializeDelayedCloseTable();
}
Пример #2
0
PVOID
NTAPI
CmpAllocateDelayItem(VOID)
{
    PCM_DELAY_ALLOC Entry;
    PCM_ALLOC_PAGE AllocPage;
    ULONG i;
    PLIST_ENTRY NextEntry;
    PAGED_CODE();
    
    /* Lock the allocation buckets */
    KeAcquireGuardedMutex(&CmpDelayAllocBucketLock);
    
    /* Look for an item on the free list */
SearchList:
    if (!IsListEmpty(&CmpFreeDelayItemsListHead))
    {
        /* Get the current entry in the list */
        NextEntry = RemoveHeadList(&CmpFreeDelayItemsListHead);
        
        /* Grab the item */
        Entry = CONTAINING_RECORD(NextEntry, CM_DELAY_ALLOC, ListEntry);
        
        /* Clear the list */
        Entry->ListEntry.Flink = Entry->ListEntry.Blink = NULL;
        
        /* Grab the alloc page */
        AllocPage = CmpGetAllocPageFromDelayAlloc(Entry);
        
        /* Decrease free entries */
        ASSERT(AllocPage->FreeCount != 0);
        AllocPage->FreeCount--;
        
        /* Release the lock */
        KeReleaseGuardedMutex(&CmpDelayAllocBucketLock);
        return Entry;
    }
    
    /* Allocate an allocation page */
    AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_CM);
    if (AllocPage)
    {
        /* Set default entries */
        AllocPage->FreeCount = CM_DELAYS_PER_PAGE;
        
        /* Loop each entry */
        for (i = 0; i < CM_DELAYS_PER_PAGE; i++)
        {
            /* Get this entry and link it */
            Entry = (PVOID)((ULONG_PTR)AllocPage +
                            FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
                            i * sizeof(CM_DELAY_ALLOC));
            InsertTailList(&CmpFreeDelayItemsListHead,
                           &Entry->ListEntry);
            
            /* Clear the KCB pointer */
            Entry->Kcb = NULL;
        }
    }
    else
    {
        /* Release the lock */
        KeReleaseGuardedMutex(&CmpDelayAllocBucketLock);
        return NULL;
    }
    
    /* Do the search again */
    goto SearchList;
}
Пример #3
0
PCM_KEY_CONTROL_BLOCK
NTAPI
CmpAllocateKeyControlBlock(VOID)
{
    PLIST_ENTRY NextEntry;
    PCM_KEY_CONTROL_BLOCK CurrentKcb;
    PCM_ALLOC_PAGE AllocPage;
    ULONG i;
    PAGED_CODE();

    /* Check if private allocations are initialized */
    if (CmpAllocInited)
    {
        /* They are, acquire the bucket lock */
        KeAcquireGuardedMutex(&CmpAllocBucketLock);
        
        /* See if there's something on the free KCB list */
SearchKcbList:
        if (!IsListEmpty(&CmpFreeKCBListHead))
        {
            /* Remove the entry */
            NextEntry = RemoveHeadList(&CmpFreeKCBListHead);
            
            /* Get the KCB */
            CurrentKcb = CONTAINING_RECORD(NextEntry,
                                           CM_KEY_CONTROL_BLOCK,
                                           FreeListEntry);
            
            /* Get the allocation page */
            AllocPage = CmpGetAllocPageFromKcb(CurrentKcb);
            
            /* Decrease the free count */
            ASSERT(AllocPage->FreeCount != 0);
            AllocPage->FreeCount--;
            
            /* Make sure this KCB is privately allocated */
            ASSERT(CurrentKcb->PrivateAlloc == 1);
            
            /* Release the allocation lock */
            KeReleaseGuardedMutex(&CmpAllocBucketLock);
            
            /* Return the KCB */
            return CurrentKcb;
        }
        
        /* Allocate an allocation page */
        AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_CM);
        if (AllocPage)
        {
            /* Set default entries */
            AllocPage->FreeCount = CM_KCBS_PER_PAGE;
            
            /* Loop each entry */
            for (i = 0; i < CM_KCBS_PER_PAGE; i++)
            {
                /* Get this entry */
                CurrentKcb = (PVOID)((ULONG_PTR)AllocPage +
                                     FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
                                     i * sizeof(CM_KEY_CONTROL_BLOCK));
                
                /* Set it up */
                CurrentKcb->PrivateAlloc = TRUE;
                CurrentKcb->DelayCloseEntry = NULL;
                InsertTailList(&CmpFreeKCBListHead,
                               &CurrentKcb->FreeListEntry);
            }
            
            /* Now go back and search the list */
            goto SearchKcbList;
        }
    }

    /* Allocate a KCB only */
    CurrentKcb = CmpAllocate(sizeof(CM_KEY_CONTROL_BLOCK), TRUE, TAG_CM);
    if (CurrentKcb)
    {
        /* Set it up */
        CurrentKcb->PrivateAlloc = 0;
        CurrentKcb->DelayCloseEntry = NULL;
    }
    
    /* Return it */
    return CurrentKcb;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
0
PCM_NAME_CONTROL_BLOCK
NTAPI
CmpGetNameControlBlock(IN PUNICODE_STRING NodeName)
{
    PCM_NAME_CONTROL_BLOCK Ncb = NULL;
    ULONG ConvKey = 0;
    PWCHAR p, pp;
    ULONG i;
    BOOLEAN IsCompressed = TRUE, Found = FALSE;
    PCM_NAME_HASH HashEntry;
    ULONG Length, NcbSize;

    /* Loop the name */
    p = NodeName->Buffer;
    for (i = 0; i < NodeName->Length; i += sizeof(WCHAR))
    {
        /* Make sure it's not a slash */
        if (*p != OBJ_NAME_PATH_SEPARATOR)
        {
            /* Add it to the hash */
            ConvKey = 37 * ConvKey + RtlUpcaseUnicodeChar(*p);
        }

        /* Next character */
        p++;
    }

    /* Set assumed lengh and loop to check */
    Length = NodeName->Length / sizeof(WCHAR);
    for (i = 0; i < (NodeName->Length / sizeof(WCHAR)); i++)
    {
        /* Check if this is a 16-bit character */
        if (NodeName->Buffer[i] > (UCHAR)-1)
        {
            /* This is the actual size, and we know we're not compressed */
            Length = NodeName->Length;
            IsCompressed = FALSE;
            break;
        }
    }

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

    /* Get the hash entry */
    HashEntry = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
    while (HashEntry)
    {
        /* Get the current NCB */
        Ncb = CONTAINING_RECORD(HashEntry, CM_NAME_CONTROL_BLOCK, NameHash);

        /* Check if the hash matches */
        if ((ConvKey == HashEntry->ConvKey) && (Length == Ncb->NameLength))
        {
            /* Assume success */
            Found = TRUE;

            /* If the NCB is compressed, do a compressed name compare */
            if (Ncb->Compressed)
            {
                /* Compare names */
                if (CmpCompareCompressedName(NodeName, Ncb->Name, Length))
                {
                    /* We failed */
                    Found = FALSE;
                }
            }
            else
            {
                /* Do a manual compare */
                p = NodeName->Buffer;
                pp = Ncb->Name;
                for (i = 0; i < Ncb->NameLength; i += sizeof(WCHAR))
                {
                    /* Compare the character */
                    if (RtlUpcaseUnicodeChar(*p) != RtlUpcaseUnicodeChar(*pp))
                    {
                        /* Failed */
                        Found = FALSE;
                        break;
                    }

                    /* Next chars */
                    p++;
                    pp++;
                }
            }

            /* Check if we found a name */
            if (Found)
            {
                /* Reference it */
                ASSERT(Ncb->RefCount != 0xFFFF);
                Ncb->RefCount++;
                break;
            }
        }

        /* Go to the next hash */
        HashEntry = HashEntry->NextHash;
    }

    /* Check if we didn't find it */
    if (!Found)
    {
        /* Allocate one */
        NcbSize = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + Length;
        Ncb = CmpAllocate(NcbSize, TRUE, TAG_CM);
        if (!Ncb)
        {
            /* Release the lock and fail */
            CmpReleaseNcbLockByKey(ConvKey);
            return NULL;
        }

        /* Clear it out */
        RtlZeroMemory(Ncb, NcbSize);

        /* Check if the name was compressed */
        if (IsCompressed)
        {
            /* Copy the compressed name */
            for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
            {
                /* Copy Unicode to ANSI */
                ((PCHAR)Ncb->Name)[i] = (CHAR)RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
            }
        }
        else
        {
            /* Copy the name directly */
            for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
            {
                /* Copy each unicode character */
                Ncb->Name[i] = RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
            }
        }

        /* Setup the rest of the NCB */
        Ncb->Compressed = IsCompressed;
        Ncb->ConvKey = ConvKey;
        Ncb->RefCount++;
        Ncb->NameLength = Length;

        /* Insert the name in the hash table */
        HashEntry = &Ncb->NameHash;
        HashEntry->NextHash = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
        GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry = HashEntry;
    }

    /* Release NCB lock */
    CmpReleaseNcbLockByKey(ConvKey);

    /* Return the NCB found */
    return Ncb;
}