Ejemplo n.º 1
0
NTSTATUS
CmiScanForSubKey(
	IN PCMHIVE RegistryHive,
	IN PCM_KEY_NODE KeyCell,
	IN PCUNICODE_STRING SubKeyName,
	IN ULONG Attributes,
	OUT PCM_KEY_NODE *pSubKeyCell,
	OUT HCELL_INDEX *pBlockOffset)
{
	PCM_KEY_FAST_INDEX HashBlock;
	PCM_KEY_NODE CurSubKeyCell;
	BOOLEAN CaseInsensitive;
	ULONG Storage;
	ULONG i;

	VERIFY_KEY_CELL(KeyCell);

	ASSERT(RegistryHive);

	*pSubKeyCell = NULL;
    CaseInsensitive = (Attributes & OBJ_CASE_INSENSITIVE) != 0;

	for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
	{
		if (KeyCell->SubKeyLists[Storage] == HCELL_NIL)
		{
			/* The key does not have any subkeys */
			continue;
		}

		/* Get hash table */
		HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
		if (!HashBlock || HashBlock->Signature != CM_KEY_FAST_LEAF)
			return STATUS_UNSUCCESSFUL;

		for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
		{
            if ((HashBlock->List[i].HashKey == 0) ||
                (CmCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey, CaseInsensitive)))
            {
                CurSubKeyCell = (PCM_KEY_NODE)HvGetCell (
                    &RegistryHive->Hive,
                    HashBlock->List[i].Cell);

                if (CmCompareKeyName(CurSubKeyCell, SubKeyName, CaseInsensitive))
                {
                    *pSubKeyCell = CurSubKeyCell;
                    *pBlockOffset = HashBlock->List[i].Cell;
                    return STATUS_SUCCESS;
                }
            }
		}
	}

	return STATUS_OBJECT_NAME_NOT_FOUND;
}
Ejemplo n.º 2
0
VALUE_SEARCH_RETURN_TYPE
NTAPI
CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
                         OUT PCELL_DATA *CellData,
                         OUT BOOLEAN *IndexIsCached,
                         OUT PHCELL_INDEX ValueListToRelease)
{
    PHHIVE Hive;
    PCACHED_CHILD_LIST ChildList;
    HCELL_INDEX CellToRelease;
    PCM_KEY_NODE KeyNode;

    /* Set defaults */
    *ValueListToRelease = HCELL_NIL;
    *IndexIsCached = FALSE;

    /* Get the hive and value cache */
    Hive = Kcb->KeyHive;
    ChildList = &Kcb->ValueCache;
    KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
    ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;

    /* Check if the value is cached */
    if (CmpIsValueCached(ChildList->ValueList))
    {
        /* It is: we don't expect this yet! */
        ASSERT_VALUE_CACHE();
        *IndexIsCached = TRUE;
        *CellData = NULL;
    }
    else
    {
        /* Make sure the KCB is locked exclusive */
        if (!(CmpIsKcbLockedExclusive(Kcb)) &&
            !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
        {
            /* We need the exclusive lock */
            return SearchNeedExclusiveLock;
        }
                
        /* Select the value list as our cell, and get the actual list array */
        CellToRelease = ChildList->ValueList;
        *CellData = (PCELL_DATA)HvGetCell(Hive, CellToRelease);
        if (!(*CellData)) return SearchFail;
        
        /* FIXME: Here we would cache the value */

        /* Return the cell to be released */
        *ValueListToRelease = CellToRelease;
    }

    /* If we got here, then the value list was found */
    return SearchSuccess;
}
Ejemplo n.º 3
0
BOOLEAN
NTAPI
CmpFreeKeyBody(IN PHHIVE Hive,
               IN HCELL_INDEX Cell)
{
    PCELL_DATA CellData;

    /* Get the key node */
    CellData = HvGetCell(Hive, Cell);
    if (!CellData) ASSERT(FALSE);

    /* Check if we can delete the child cells */
    if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
    {
        /* Check if we have a security cell */
        if (CellData->u.KeyNode.Security != HCELL_NIL)
        {
            /* Free the security cell */
            HvFreeCell(Hive, CellData->u.KeyNode.Security);
        }

        /* Check if we have a class */
        if (CellData->u.KeyNode.ClassLength > 0)
        {
            /* Free it */
            HvFreeCell(Hive, CellData->u.KeyNode.Class);
        }
    }

    /* Release and free the cell */
    HvReleaseCell(Hive, Cell);
    HvFreeCell(Hive, Cell);
    return TRUE;
}
Ejemplo n.º 4
0
static NTSTATUS
CmiAllocateHashTableCell (
	IN PCMHIVE RegistryHive,
	OUT PCM_KEY_FAST_INDEX *HashBlock,
	OUT HCELL_INDEX *HBOffset,
	IN USHORT SubKeyCount,
	IN HSTORAGE_TYPE Storage)
{
	PCM_KEY_FAST_INDEX NewHashBlock;
	ULONG NewHashSize;
	NTSTATUS Status;

	Status = STATUS_SUCCESS;
	*HashBlock = NULL;
	NewHashSize = FIELD_OFFSET(CM_KEY_FAST_INDEX, List) +
		(SubKeyCount * sizeof(CM_INDEX));
	*HBOffset = HvAllocateCell(&RegistryHive->Hive, NewHashSize, Storage, HCELL_NIL);

	if (*HBOffset == HCELL_NIL)
	{
		Status = STATUS_INSUFFICIENT_RESOURCES;
	}
	else
	{
		NewHashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, *HBOffset);
		NewHashBlock->Signature = CM_KEY_FAST_LEAF;
		NewHashBlock->Count = 0;
		*HashBlock = NewHashBlock;
	}

	return Status;
}
Ejemplo n.º 5
0
static BOOL
ConnectRegistry(
	IN HKEY RootKey,
	IN PCMHIVE HiveToConnect,
	IN LPCWSTR Path)
{
	NTSTATUS Status;
	MEMKEY NewKey;
	LONG rc;

	Status = CmiInitializeTempHive(HiveToConnect);
	if (!NT_SUCCESS(Status))
	{
		DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
		return FALSE;
	}

	/* Create key */
	rc = RegCreateKeyW(
		RootKey,
		Path,
		(PHKEY)&NewKey);
	if (rc != ERROR_SUCCESS)
		return FALSE;

	NewKey->RegistryHive = HiveToConnect;
	NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell;
	NewKey->KeyCell = (PCM_KEY_NODE)HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
	return TRUE;
}
Ejemplo n.º 6
0
NTSTATUS
CmiScanForValueKey(
	IN PCMHIVE RegistryHive,
	IN PCM_KEY_NODE KeyCell,
	IN PCUNICODE_STRING ValueName,
	OUT PCM_KEY_VALUE *pValueCell,
	OUT HCELL_INDEX *pValueCellOffset)
{
	PVALUE_LIST_CELL ValueListCell;
	PCM_KEY_VALUE CurValueCell;
	ULONG i;

	*pValueCell = NULL;
	*pValueCellOffset = HCELL_NIL;

	/* The key does not have any values */
	if (KeyCell->ValueList.List == HCELL_NIL)
    {
		return STATUS_OBJECT_NAME_NOT_FOUND;
    }

	ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);

	VERIFY_VALUE_LIST_CELL(ValueListCell);

	for (i = 0; i < KeyCell->ValueList.Count; i++)
	{
		CurValueCell = (PCM_KEY_VALUE)HvGetCell(
			&RegistryHive->Hive,
			ValueListCell->ValueOffset[i]);

		if (CmComparePackedNames(ValueName,
                                 (PUCHAR)CurValueCell->Name,
                                 CurValueCell->NameLength,
                                 (CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE,
                                 TRUE))
		{
			*pValueCell = CurValueCell;
			*pValueCellOffset = ValueListCell->ValueOffset[i];
			return STATUS_SUCCESS;
		}
	}

	return STATUS_OBJECT_NAME_NOT_FOUND;
}
Ejemplo n.º 7
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);
    }
}
Ejemplo n.º 8
0
static NTSTATUS
CmiAllocateValueCell(
	IN PCMHIVE RegistryHive,
	OUT PCM_KEY_VALUE *ValueCell,
	OUT HCELL_INDEX *VBOffset,
	IN PCUNICODE_STRING ValueName,
	IN HSTORAGE_TYPE Storage)
{
	PCM_KEY_VALUE NewValueCell;
	BOOLEAN Packable;
	USHORT NameLength, i;
	NTSTATUS Status;

	Status = STATUS_SUCCESS;

	NameLength = CmiGetPackedNameLength(ValueName, &Packable);

	DPRINT("ValueName->Length %u  NameLength %u\n", ValueName->Length, NameLength);

	*VBOffset = HvAllocateCell(&RegistryHive->Hive, sizeof(CM_KEY_VALUE) + NameLength, Storage, HCELL_NIL);
	if (*VBOffset == HCELL_NIL)
	{
		Status = STATUS_INSUFFICIENT_RESOURCES;
	}
	else
	{
		NewValueCell = (PCM_KEY_VALUE)HvGetCell (&RegistryHive->Hive, *VBOffset);
		NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE;
		NewValueCell->NameLength = (USHORT)NameLength;
		if (Packable)
		{
			/* Pack the value name */
			for (i = 0; i < NameLength; i++)
				((PCHAR)NewValueCell->Name)[i] = (CHAR)ValueName->Buffer[i];
			NewValueCell->Flags |= VALUE_COMP_NAME;
		}
		else
		{
			/* Copy the value name */
			RtlCopyMemory(
				NewValueCell->Name,
				ValueName->Buffer,
				NameLength);
			NewValueCell->Flags = 0;
		}
		NewValueCell->Type = 0;
		NewValueCell->DataLength = 0;
		NewValueCell->Data = HCELL_NIL;
		*ValueCell = NewValueCell;
	}

	return Status;
}
Ejemplo n.º 9
0
static
BOOLEAN
RegImportIndexSubKey(
    PHHIVE Hive,
    PCM_KEY_INDEX IndexCell,
    FRLDRHKEY ParentKey)
{
    ULONG i;

    TRACE("IndexCell: %x\n", IndexCell);

    /* Enumerate and add subkeys */
    if ((IndexCell->Signature == CM_KEY_INDEX_ROOT) ||
        (IndexCell->Signature == CM_KEY_INDEX_LEAF))
    {
        for (i = 0; i < IndexCell->Count; i++)
        {
            PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]);
            if (!RegImportIndexSubKey(Hive, SubIndexCell, ParentKey))
                return FALSE;
        }
    }
    else if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
             (IndexCell->Signature == CM_KEY_HASH_LEAF))
    {
        PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
        for (i = 0; i < HashCell->Count; i++)
        {
            PCM_KEY_NODE SubKeyCell = HvGetCell(Hive, HashCell->List[i].Cell);
            if (!RegImportSubKey(Hive, SubKeyCell, ParentKey))
                return FALSE;
        }
    }
    else
    {
        ASSERT(FALSE);
    }

    return TRUE;
}
Ejemplo n.º 10
0
VOID
CmpFreeKeyBody(
    PHHIVE Hive,
    HCELL_INDEX Cell
    )
/*++

Routine Description:

    Free storage for the key entry Hive.Cell refers to, including
    its class and security data.  Will NOT free child list or value list.

Arguments:

    Hive - supplies a pointer to the hive control structure for the hive

    Cell - supplies index of key to free

Return Value:

    NTSTATUS - Result code from call, among the following:

        <TBS>

--*/
{
    PCELL_DATA key;

    //
    // map in the cell
    //
    key = HvGetCell(Hive, Cell);

    if (!(key->u.KeyNode.Flags & KEY_HIVE_EXIT)) {
        if (key->u.KeyNode.Security != HCELL_NIL) {
            HvFreeCell(Hive, key->u.KeyNode.Security);
        }

        if (key->u.KeyNode.ClassLength > 0) {
            HvFreeCell(Hive, key->u.KeyNode.Class);
        }
    }

    //
    // unmap the cell itself and free it
    //
    HvFreeCell(Hive, Cell);

    return;
}
Ejemplo n.º 11
0
VALUE_SEARCH_RETURN_TYPE
NTAPI
CmpGetValueKeyFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
                        IN PCELL_DATA CellData,
                        IN ULONG Index,
                        OUT PCM_CACHED_VALUE **CachedValue,
                        OUT PCM_KEY_VALUE *Value,
                        IN BOOLEAN IndexIsCached,
                        OUT BOOLEAN *ValueIsCached,
                        OUT PHCELL_INDEX CellToRelease)
{
    PHHIVE Hive;
    PCM_KEY_VALUE KeyValue;
    HCELL_INDEX Cell;

    /* Set defaults */
    *CellToRelease = HCELL_NIL;
    *Value = NULL;
    *ValueIsCached = FALSE;

    /* Get the hive */
    Hive = Kcb->KeyHive;

    /* Check if the index was cached */
    if (IndexIsCached)
    {
        /* Not expected yet! */
        ASSERT_VALUE_CACHE();
        *ValueIsCached = TRUE;
    }
    else
    {
        /* Get the cell index and the key value associated to it */
        Cell = CellData->u.KeyList[Index];
        KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
        if (!KeyValue) return SearchFail;

        /* Return the cell and the actual key value */
        *CellToRelease = Cell;
        *Value = KeyValue;
    }

    /* If we got here, then we found the key value */
    return SearchSuccess;
}
Ejemplo n.º 12
0
static MEMKEY
CreateInMemoryStructure(
	IN PCMHIVE RegistryHive,
	IN HCELL_INDEX KeyCellOffset,
	IN PCUNICODE_STRING KeyName)
{
	MEMKEY Key;

	Key = (MEMKEY) malloc (sizeof(KEY));
	if (!Key)
		return NULL;

	InitializeListHead (&Key->SubKeyList);
	InitializeListHead (&Key->ValueList);
	InitializeListHead (&Key->KeyList);

	Key->SubKeyCount = 0;
	Key->ValueCount = 0;

	Key->NameSize = KeyName->Length;
	/* FIXME: It's not enough to allocate this way, because later
	          this memory gets overwritten with bigger names */
	Key->Name = malloc (Key->NameSize);
	if (!Key->Name)
		return NULL;
	memcpy(Key->Name, KeyName->Buffer, KeyName->Length);

	Key->DataType = 0;
	Key->DataSize = 0;
	Key->Data = NULL;

	Key->RegistryHive = RegistryHive;
	Key->KeyCellOffset = KeyCellOffset;
	Key->KeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
	if (!Key->KeyCell)
	{
		free(Key);
		return NULL;
	}
	Key->LinkedKey = NULL;
	return Key;
}
Ejemplo n.º 13
0
NTSTATUS
NTAPI
CmpFreeKeyByCell(IN PHHIVE Hive,
                 IN HCELL_INDEX Cell,
                 IN BOOLEAN Unlink)
{
    PCM_KEY_NODE CellData, ParentData;
    PCELL_DATA ListData;
    ULONG i;
    BOOLEAN Result;

    /* Mark the entire key dirty */
    CmpMarkKeyDirty(Hive, Cell, TRUE);

    /* Get the target node and release it */
    CellData = HvGetCell(Hive, Cell);
    if (!CellData) ASSERT(FALSE);
    HvReleaseCell(Hive, Cell);

    /* Make sure we don't have subkeys */
    ASSERT(CellData->SubKeyCounts[Stable] + CellData->SubKeyCounts[Volatile] == 0);

    /* Check if we have to unlink */
    if (Unlink)
    {
        /* Remove the subkey */
        Result = CmpRemoveSubKey(Hive, CellData->Parent, Cell);
        if (!Result) return STATUS_INSUFFICIENT_RESOURCES;

        /* Get the parent node and release it */
        ParentData = HvGetCell(Hive, CellData->Parent);
        if (!ParentData) ASSERT(FALSE);
        HvReleaseCell(Hive, CellData->Parent);

        /* Check if the parent node has no more subkeys */
        if (ParentData->SubKeyCounts[Stable] + ParentData->SubKeyCounts[Volatile] == 0)
        {
            /* Then free the cached name/class lengths */
            ParentData->MaxNameLen  = 0;
            ParentData->MaxClassLen = 0;
        }
    }

    // TODO: Handle predefined keys (Flags: KEY_PREDEF_HANDLE)
    /* If this is an exit node, we don't have values */
    if (!(CellData->Flags & KEY_HIVE_EXIT))
    {
        /* Check if we have any values */
        if (CellData->ValueList.Count > 0)
        {
            /* Get the value list and release it */
            ListData = HvGetCell(Hive, CellData->ValueList.List);
            if (!ListData) ASSERT(FALSE);
            HvReleaseCell(Hive, CellData->ValueList.List);

            /* Loop every value */
            for (i = 0; i < CellData->ValueList.Count; i++)
            {
                /* Free it */
                if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
            }

            /* Free the value list */
            HvFreeCell(Hive, CellData->ValueList.List);
        }

        /* Free the key security descriptor */
        CmpFreeSecurityDescriptor(Hive, Cell);
    }

    /* Free the key body itself, and then return our status */
    if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
    return STATUS_SUCCESS;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
HCELL_INDEX
CmpWalkPath(
    PHHIVE      SystemHive,
    HCELL_INDEX ParentCell,
    PWSTR       Path
    )
/*++

Routine Description:

    Walk the path.

Arguments:

    SystemHive - hive

    ParentCell - where to start

    Path - string to walk

Return Value:

    HCELL_INDEX of found key cell, or HCELL_NIL for error

--*/
{
    UNICODE_STRING  PathString;
    UNICODE_STRING  NextName;
    BOOLEAN         Last;
    HCELL_INDEX     KeyCell;
    PCM_KEY_NODE    Node;

    //
    // don't bother counting/releasing used cells
    //
    ASSERT( SystemHive->ReleaseCellRoutine == NULL );

    KeyCell = ParentCell;
    RtlInitUnicodeString(&PathString, Path);

    while (TRUE) {

        CmpGetNextName(&PathString, &NextName, &Last);

        if (NextName.Length == 0) {
            return KeyCell;
        }

        Node = (PCM_KEY_NODE)HvGetCell(SystemHive,KeyCell);
        if( Node == NULL ) {
            //
            // we couldn't map a view for the bin containing this cell
            //
            return HCELL_NIL;
        }
        KeyCell = CmpFindSubKeyByName(SystemHive,
                                      Node,
                                      &NextName);

        if (KeyCell == HCELL_NIL) {
            return HCELL_NIL;
        }
    }
}
Ejemplo n.º 16
0
VALUE_SEARCH_RETURN_TYPE
NTAPI
CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
                            IN PCUNICODE_STRING Name,
                            OUT PCM_CACHED_VALUE **CachedValue,
                            OUT ULONG *Index,
                            OUT PCM_KEY_VALUE *Value,
                            OUT BOOLEAN *ValueIsCached,
                            OUT PHCELL_INDEX CellToRelease)
{
    PHHIVE Hive;
    VALUE_SEARCH_RETURN_TYPE SearchResult = SearchFail;
    LONG Result;
    UNICODE_STRING SearchName;
    PCELL_DATA CellData;
    PCACHED_CHILD_LIST ChildList;
    PCM_KEY_VALUE KeyValue;
    BOOLEAN IndexIsCached;
    ULONG i = 0;
    HCELL_INDEX Cell = HCELL_NIL;
    PCM_KEY_NODE KeyNode;

    /* Set defaults */
    *CellToRelease = HCELL_NIL;
    *Value = NULL;

    /* Get the hive and child list */
    Hive = Kcb->KeyHive;
    ChildList = &Kcb->ValueCache;
    KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
    ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;

    /* Check if the child list has any entries */
    if (ChildList->Count != 0)
    {
        /* Get the value list associated to this child list */
        SearchResult = CmpGetValueListFromCache(Kcb,
                                                &CellData,
                                                &IndexIsCached,
                                                &Cell);
        if (SearchResult != SearchSuccess)
        {
            /* We either failed or need the exclusive lock */
            ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
            ASSERT(Cell == HCELL_NIL);
            return SearchResult;
        }

        /* The index shouldn't be cached right now */
        if (IndexIsCached) ASSERT_VALUE_CACHE();

        /* Loop every value */
        while (TRUE)
        {
            /* Check if there's any cell to release */
            if (*CellToRelease != HCELL_NIL)
            {
                /* Release it now */
                HvReleaseCell(Hive, *CellToRelease);
                *CellToRelease = HCELL_NIL;
            }

            /* Get the key value for this index */
            SearchResult =  CmpGetValueKeyFromCache(Kcb,
                                                    CellData,
                                                    i,
                                                    CachedValue,
                                                    Value,
                                                    IndexIsCached,
                                                    ValueIsCached,
                                                    CellToRelease);
            if (SearchResult != SearchSuccess)
            {
                /* We either failed or need the exclusive lock */
                ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
                ASSERT(Cell == HCELL_NIL);
                return SearchResult;
            }

            /* Check if the both the index and the value are cached */
            if ((IndexIsCached) && (*ValueIsCached))
            {
                /* We don't expect this yet */
                ASSERT_VALUE_CACHE();
                Result = -1;
            }
            else
            {
                /* No cache, so try to compare the name. Is it compressed? */
                KeyValue = *Value;
                if (KeyValue->Flags & VALUE_COMP_NAME)
                {
                    /* It is, do a compressed name comparison */
                    Result = CmpCompareCompressedName(Name,
                                                      KeyValue->Name,
                                                      KeyValue->NameLength);
                }
                else
                {
                    /* It's not compressed, so do a standard comparison */
                    SearchName.Length = KeyValue->NameLength;
                    SearchName.MaximumLength = SearchName.Length;
                    SearchName.Buffer = KeyValue->Name;
                    Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
                }
            }

            /* Check if we found the value data */
            if (!Result)
            {
                /* We have, return the index of the value and success */
                *Index = i;
                SearchResult = SearchSuccess;
                goto Quickie;
            }

            /* We didn't find it, try the next entry */
            if (++i == ChildList->Count)
            {
                /* The entire list was parsed, fail */
                *Value = NULL;
                SearchResult = SearchFail;
                goto Quickie;
            }
        }
    }

    /* We should only get here if the child list is empty */
    ASSERT(ChildList->Count == 0);

Quickie:
    /* Release the value list cell if required, and return search result */
    if (Cell != HCELL_NIL) HvReleaseCell(Hive, Cell);
    return SearchResult;
}
Ejemplo n.º 17
0
VOID
CmGetSystemControlValues(
    __in PVOID                   SystemHiveBuffer,
    __inout PCM_SYSTEM_CONTROL_VECTOR  ControlVector
    )
/*++

Routine Description:

    Look for registry values in current control set, as specified
    by entries in ControlVector.  Report data for value entries
    (if any) to variables ControlVector points to.

Arguments:

    SystemHiveBuffer - pointer to flat image of the system hive

    ControlVector - pointer to structure that describes what values
                    to pull out and store

Return Value:

    NONE.

--*/
{
    NTSTATUS        status;
    PHHIVE          SystemHive;
    HCELL_INDEX     RootCell;
    HCELL_INDEX     BaseCell;
    UNICODE_STRING  Name;
    HCELL_INDEX     KeyCell;
    HCELL_INDEX     ValueCell;
    PCM_KEY_VALUE   ValueBody;
    ULONG           Length;
    BOOLEAN         AutoSelect;
    BOOLEAN         small;
    ULONG           tmplength;
    PCM_KEY_NODE    Node;

    //
    // set up to read flat system hive image loader passes us
    //
    RtlZeroMemory((PVOID)&CmControlHive, sizeof(CmControlHive));
    SystemHive = &(CmControlHive.Hive);
    CmpInitHiveViewList((PCMHIVE)SystemHive);
    CmpInitSecurityCache((PCMHIVE)SystemHive);
    status = HvInitializeHive(
                SystemHive,
                HINIT_FLAT,
                HIVE_VOLATILE,
                HFILE_TYPE_PRIMARY,
                SystemHiveBuffer,
                NULL,
                NULL,
                NULL,
                NULL,
                NULL,
                NULL,
                1,
                NULL
                );
    if (!NT_SUCCESS(status)) {
         CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,1,SystemHive,status);
    }

    //
    // don't bother locking/releasing cells
    //
    ASSERT( SystemHive->ReleaseCellRoutine == NULL );
    //
    // get hive.cell of root of current control set
    //
    RootCell = ((PHBASE_BLOCK)SystemHiveBuffer)->RootCell;
    RtlInitUnicodeString(&Name, L"current");
    BaseCell = CmpFindControlSet(
                    SystemHive,
                    RootCell,
                    &Name,
                    &AutoSelect
                    );
    if (BaseCell == HCELL_NIL) {
        CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,2,SystemHive,&Name);
    }

    Node = (PCM_KEY_NODE)HvGetCell(SystemHive,BaseCell);
    if( Node == NULL ) {
        //
        // we couldn't map a view for the bin containing this cell
        //
        return;
    }
    RtlInitUnicodeString(&Name, L"control");
    BaseCell = CmpFindSubKeyByName(SystemHive,
                                   Node,
                                   &Name);
    if (BaseCell == HCELL_NIL) {
        CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,3,Node,&Name);
    }

    //
    // SystemHive.BaseCell = \registry\machine\system\currentcontrolset\control
    //

    //
    // step through vector, trying to fetch each value
    //
    while (ControlVector->KeyPath != NULL) {

        //
        //  Assume we will fail to find the key or value.
        //
        
        Length = (ULONG)-1;

        KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);

        if (KeyCell != HCELL_NIL) {

            //
            // found the key, look for the value entry
            //
            Node = (PCM_KEY_NODE)HvGetCell(SystemHive,KeyCell);
            if( Node == NULL ) {
                //
                // we couldn't map a view for the bin containing this cell
                //
                return;
            }
            RtlInitUnicodeString(&Name, ControlVector->ValueName);
            ValueCell = CmpFindValueByName(SystemHive,
                                           Node,
                                           &Name);
            if (ValueCell != HCELL_NIL) {

                //
                // SystemHive.ValueCell is value entry body
                //

                if (ControlVector->BufferLength == NULL) {
                    tmplength = sizeof(ULONG);
                } else {
                    tmplength = *(ControlVector->BufferLength);
                }

                ValueBody = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
                if( ValueBody == NULL ) {
                    //
                    // we couldn't map a view for the bin containing this cell
                    //
                    return;
                }

                small = CmpIsHKeyValueSmall(Length, ValueBody->DataLength);

                if (tmplength < Length) {
                    Length = tmplength;
                }

                if (Length > 0) {

                    PCELL_DATA  Buffer;
                    BOOLEAN     BufferAllocated;
                    ULONG       realsize;
                    HCELL_INDEX CellToRelease;

                    ASSERT((small ? (Length <= CM_KEY_VALUE_SMALL) : TRUE));
                    //
                    // get the data from source, regardless of the size
                    //
                    if( CmpGetValueData(SystemHive,ValueBody,&realsize,&Buffer,&BufferAllocated,&CellToRelease) == FALSE ) {
                        //
                        // insufficient resources; return NULL
                        //
                        ASSERT( BufferAllocated == FALSE );
                        ASSERT( Buffer == NULL );
                        return;
                    }

                    RtlCopyMemory(
                        ControlVector->Buffer,
                        Buffer,
                        Length
                        );

                    //
                    // cleanup the temporary buffer
                    //
                    if( BufferAllocated == TRUE ) {
                        ExFreePool( Buffer );
                    }
                    if( CellToRelease != HCELL_NIL ) {
                        HvReleaseCell(SystemHive,CellToRelease);
                    }
                }

                if (ControlVector->Type != NULL) {
                    *(ControlVector->Type) = ValueBody->Type;
                }
            }
        }

        //
        // Stash the length of result (-1 if nothing was found)
        //
        
        if (ControlVector->BufferLength != NULL) {
            *(ControlVector->BufferLength) = Length;
        }

        ControlVector++;
    }

    //
    // Get the default locale ID for the system from the registry.
    //

    if (CmDefaultLanguageIdType == REG_SZ) {
        PsDefaultSystemLocaleId = (LCID) CmpConvertLangId( 
                                                CmDefaultLanguageId,
                                                CmDefaultLanguageIdLength);
    } else {
        PsDefaultSystemLocaleId = 0x00000409;
    }

    //
    // Get the install (native UI) language ID for the system from the registry.
    //

    if (CmInstallUILanguageIdType == REG_SZ) {
        PsInstallUILanguageId =  CmpConvertLangId( 
                                                CmInstallUILanguageId,
                                                CmInstallUILanguageIdLength);
    } else {
        PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
    }

    //
    // Set the default thread locale to the default system locale
    // for now.  This will get changed as soon as somebody logs in.
    // Use the install (native) language id as our default UI language id. 
    // This also will get changed as soon as somebody logs in.
    //

    PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
    PsDefaultUILanguageId = PsInstallUILanguageId;
}
Ejemplo n.º 18
0
ULONG
CmpCheckValueList(
    PHHIVE      Hive,
    PCELL_DATA List,
    ULONG       Count
    )
/*++

Routine Description:

    Check consistency of a value list.
        .   Each element allocated?
        .   Each element have valid signature?
        .   Data properly allocated?

Arguments:

    Hive - containing Hive.

    List - pointer to an array of HCELL_INDEX entries.

    Count - number of entries in list.

Return Value:

    0 if Hive is OK.  Error return indicator if not.

    RANGE:  5000 - 5999

--*/
{
    ULONG   i;
    HCELL_INDEX Cell;
    PCELL_DATA pcell;
    ULONG   size;
    ULONG   usedlen;
    ULONG   DataLength;
    HCELL_INDEX Data;
    ULONG   rc = 0;

    CmpCheckValueListDebug.Hive = Hive;
    CmpCheckValueListDebug.Status = 0;
    CmpCheckValueListDebug.List = List;
    CmpCheckValueListDebug.Index = (ULONG)-1;
    CmpCheckValueListDebug.Cell = 0;   // NOT HCELL_NIL
    CmpCheckValueListDebug.CellPoint = NULL;

    for (i = 0; i < Count; i++) {

        //
        // Check out value entry's refs.
        //
        Cell = List->u.KeyList[i];
        if (Cell == HCELL_NIL) {
            KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
            KdPrint(("\tEntry is null\n"));
            rc = 5010;
            CmpCheckValueListDebug.Status = rc;
            CmpCheckValueListDebug.Index = i;
            CmpCheckValueListDebug.Cell = Cell;
            return rc;
        }
        if (HvIsCellAllocated(Hive, Cell) == FALSE) {
            KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
            KdPrint(("\tEntry is not allocated\n"));
            rc = 5020;
            CmpCheckValueListDebug.Status = rc;
            CmpCheckValueListDebug.Index = i;
            CmpCheckValueListDebug.Cell = Cell;
            return rc;
        } else {
            SetUsed(Hive, Cell);
        }

        //
        // Check out the value entry itself
        //
        pcell = HvGetCell(Hive, Cell);
        size = HvGetCellSize(Hive, pcell);
        if (pcell->u.KeyValue.Signature != CM_KEY_VALUE_SIGNATURE) {
            KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
            KdPrint(("\tCell:%08lx - invalid value signature\n", Cell));
            rc = 5030;
            CmpCheckValueListDebug.Status = rc;
            CmpCheckValueListDebug.Index = i;
            CmpCheckValueListDebug.Cell = Cell;
            CmpCheckValueListDebug.CellPoint = pcell;
            return rc;
        }
        usedlen = FIELD_OFFSET(CM_KEY_VALUE, Name) + pcell->u.KeyValue.NameLength;
        if (usedlen > size) {
            KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
            KdPrint(("\tCell:%08lx - value bigger than containing cell\n", Cell));
            rc = 5040;
            CmpCheckValueListDebug.Status = rc;
            CmpCheckValueListDebug.Index = i;
            CmpCheckValueListDebug.Cell = Cell;
            CmpCheckValueListDebug.CellPoint = pcell;
            return rc;
        }

        //
        // Check out value entry's data
        //
        DataLength = pcell->u.KeyValue.DataLength;
        if (DataLength < CM_KEY_VALUE_SPECIAL_SIZE) {
            Data = pcell->u.KeyValue.Data;
            if ((DataLength == 0) && (Data != HCELL_NIL)) {
                KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
                KdPrint(("\tCell:%08lx Data:%08lx - data not null\n", Cell, Data));
                rc = 5050;
                CmpCheckValueListDebug.Status = rc;
                CmpCheckValueListDebug.Index = i;
                CmpCheckValueListDebug.Cell = Cell;
                CmpCheckValueListDebug.CellPoint = pcell;
                return rc;
            }
            if (DataLength > 0) {
                if (HvIsCellAllocated(Hive, Data) == FALSE) {
                    KdPrint(("CmpCheckValueList: List:%08lx i:%08lx\n", List, i));
                    KdPrint(("\tCell:%08lx Data:%08lx - unallocated\n", Cell, Data));
                    rc = 5060;
                    CmpCheckValueListDebug.Status = rc;
                    CmpCheckValueListDebug.Index = i;
                    CmpCheckValueListDebug.Cell = Cell;
                    CmpCheckValueListDebug.CellPoint = pcell;
                    return rc;
                } else {
                    SetUsed(Hive, Data);
                }
            }
        }
    }
    return rc;
}
Ejemplo n.º 19
0
BOOLEAN
NTAPI
CmpFindNameInList(IN PHHIVE Hive,
                  IN PCHILD_LIST ChildList,
                  IN PUNICODE_STRING Name,
                  IN PULONG ChildIndex,
                  IN PHCELL_INDEX CellIndex)
{
    PCELL_DATA CellData;
    HCELL_INDEX CellToRelease = HCELL_NIL;
    ULONG i;
    PCM_KEY_VALUE KeyValue;
    LONG Result;
    UNICODE_STRING SearchName;
    BOOLEAN Success;

    /* Make sure there's actually something on the list */
    if (ChildList->Count != 0)
    {
        /* Get the cell data */
        CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
        if (!CellData)
        {
            /* Couldn't get the cell... tell the caller */
            *CellIndex = HCELL_NIL;
            return FALSE;
        }

        /* Now loop every entry */
        for (i = 0; i < ChildList->Count; i++)
        {
            /* Check if we have a cell to release */
            if (CellToRelease != HCELL_NIL)
            {
                /* Release it */
                HvReleaseCell(Hive, CellToRelease);
                CellToRelease = HCELL_NIL;
            }

            /* Get this value */
            KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
            if (!KeyValue)
            {
                /* Return with no data found */
                *CellIndex = HCELL_NIL;
                Success = FALSE;
                goto Return;
            }

            /* Save the cell to release */
            CellToRelease = CellData->u.KeyList[i];

            /* Check if it's a compressed value name */
            if (KeyValue->Flags & VALUE_COMP_NAME)
            {
                /* Use the compressed name check */
                Result = CmpCompareCompressedName(Name,
                                                  KeyValue->Name,
                                                  KeyValue->NameLength);
            }
            else
            {
                /* Setup the Unicode string */
                SearchName.Length = KeyValue->NameLength;
                SearchName.MaximumLength = SearchName.Length;
                SearchName.Buffer = KeyValue->Name;
                Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
            }

            /* Check if we found it */
            if (!Result)
            {
                /* We did...return info to caller */
                if (ChildIndex) *ChildIndex = i;
                *CellIndex = CellData->u.KeyList[i];

                /* Set success state */
                Success = TRUE;
                goto Return;
            }
        }

        /* Got to the end of the list */
        if (ChildIndex) *ChildIndex = i;
        *CellIndex = HCELL_NIL;

        /* Nothing found if we got here */
        Success = TRUE;
        goto Return;
    }

    /* Nothing found...check if the caller wanted more info */
    ASSERT(ChildList->Count == 0);
    if (ChildIndex) *ChildIndex = 0;
    *CellIndex = HCELL_NIL;

    /* Nothing found if we got here */
    return TRUE;

Return:
    /* Release the first cell we got */
    if (CellData) HvReleaseCell(Hive, ChildList->List);

    /* Release the secondary one, if we have one */
    if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
    return Success;
}
Ejemplo n.º 20
0
ULONG
CmpCheckRegistry2(
    HCELL_INDEX Cell,
    HCELL_INDEX ParentCell
    )
/*++

Routine Description:

    Check consistency of the registry, from a particular cell on down.

        .   Check that the cell's value list, child key list, class,
            security are OK.
        .   Check that each value entry IN the list is OK.
        .   Apply self to each child key list.

Globals:

    CmpCheckHive - hive we're working on

    CmpCheckClean - flag TRUE -> clean off volatiles, FALSE -> don't

Arguments:

    Cell - HCELL_INDEX of subkey to work on.

    ParentCell - expected value of parent cell for Cell, unless
                 HCELL_NIL, in which case ignore.

Return Value:

    0 if Hive is OK.  Error return indicator if not.

    RANGE:  4000 - 4999

--*/
{
    ULONG       Index = 0;
    HCELL_INDEX StartCell = Cell;
    HCELL_INDEX SubKey;
    ULONG       rc = 0;
    PCELL_DATA  pcell;


    CmpCheckRegistry2Debug.Hive = CmpCheckHive;
    CmpCheckRegistry2Debug.Status = 0;

    //
    // A jump to NewKey amounts to a virtual call to check the
    // next child cell. (a descent into the tree)
    //
    // Cell, ParentCell, Index, and globals are defined
    //
    NewKey:
        rc = CmpCheckKey(Cell, ParentCell);
        if (rc != 0) {
            KdPrint(("\tChild is list entry #%08lx\n", Index));
            CmpCheckRegistry2Debug.Status = rc;
            return rc;
        }

        //
        // save Index and check out children
        //
        pcell = HvGetCell(CmpCheckHive, Cell);
        pcell->u.KeyNode.WorkVar = Index;

        for (Index = 0; Index<pcell->u.KeyNode.SubKeyCounts[Stable]; Index++) {

            SubKey = CmpFindSubKeyByNumber(CmpCheckHive,
                                           (PCM_KEY_NODE)HvGetCell(CmpCheckHive,Cell),
                                           Index);

            //
            // "recurse" onto child
            //
            ParentCell = Cell;
            Cell = SubKey;
            goto NewKey;

            ResumeKey:;                 // A jump here is a virtual return
                                        // Cell, ParentCell and Index
                                        // must be defined
        }

        //
        // since we're here, we've checked out all the children
        // of the current cell.
        //
        if (Cell == StartCell) {

            //
            // we are done
            //
            return 0;
        }

        //
        // "return" to "parent instance"
        //
        pcell = HvGetCell(CmpCheckHive, Cell);
        Index = pcell->u.KeyNode.WorkVar;

        Cell = ParentCell;

        pcell = HvGetCell(CmpCheckHive, Cell);
        ParentCell = pcell->u.KeyNode.Parent;

        goto ResumeKey;
}
Ejemplo n.º 21
0
ULONG
CmpCheckKey(
    HCELL_INDEX Cell,
    HCELL_INDEX ParentCell
    )
/*++

Routine Description:

    Check consistency of the registry, for a particular cell

        .   Check that the cell's value list, child key list, class,
            security are OK.
        .   Check that each value entry IN the list is OK.

Globals:

    CmpCheckHive - hive we're working on

    CmpCheckClean - flag TRUE -> clean off volatiles, FALSE -> don't

Arguments:

    Cell - HCELL_INDEX of subkey to work on.

    ParentCell - expected value of parent cell for Cell, unless
                 HCELL_NIL, in which case ignore.

Return Value:

    0 if Hive is OK.  Error return indicator if not.

    RANGE:  4000 - 4999

--*/
{
    PCELL_DATA      pcell;
    ULONG           size;
    ULONG           usedlen;
    ULONG           ClassLength;
    HCELL_INDEX     Class;
    ULONG           ValueCount;
    HCELL_INDEX     ValueList;
    HCELL_INDEX     Security;
    ULONG           rc = 0;
    ULONG           nrc = 0;
    ULONG           i;
    PCM_KEY_INDEX   Root;
    PCM_KEY_INDEX   Leaf;
    ULONG           SubCount;

    CmpCheckKeyDebug.Hive = CmpCheckHive;
    CmpCheckKeyDebug.Status = 0;
    CmpCheckKeyDebug.Cell = Cell;
    CmpCheckKeyDebug.CellPoint = NULL;
    CmpCheckKeyDebug.RootPoint = NULL;
    CmpCheckKeyDebug.Index = (ULONG)-1;

    //
    // Check key itself
    //
    if (! HvIsCellAllocated(CmpCheckHive, Cell)) {
        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
        KdPrint(("\tNot allocated\n"));
        rc = 4010;
        CmpCheckKeyDebug.Status = rc;
        return rc;
    }
    pcell = HvGetCell(CmpCheckHive, Cell);
    SetUsed(CmpCheckHive, Cell);

    CmpCheckKeyDebug.CellPoint = pcell;

    size = HvGetCellSize(CmpCheckHive, pcell);
    if (size > REG_MAX_PLAUSIBLE_KEY_SIZE) {
        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
        KdPrint(("\tImplausible size %lx\n", size));
        rc = 4020;
        CmpCheckKeyDebug.Status = rc;
        return rc;
    }
    usedlen = FIELD_OFFSET(CM_KEY_NODE, Name) + pcell->u.KeyNode.NameLength;
    if (usedlen > size) {
        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
        KdPrint(("\tKey is bigger than containing cell.\n"));
        rc = 4030;
        CmpCheckKeyDebug.Status = rc;
        return rc;
    }
    if (pcell->u.KeyNode.Signature != CM_KEY_NODE_SIGNATURE) {
        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
        KdPrint(("\tNo key signature\n"));
        rc = 4040;
        CmpCheckKeyDebug.Status = rc;
        return rc;
    }
    if (ParentCell != HCELL_NIL) {
        if (pcell->u.KeyNode.Parent != ParentCell) {
            KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
            KdPrint(("\tWrong parent value.\n"));
            rc = 4045;
            CmpCheckKeyDebug.Status = rc;
            return rc;
        }
    }
    ClassLength = pcell->u.KeyNode.ClassLength;
    Class = pcell->u.KeyNode.Class;
    ValueCount = pcell->u.KeyNode.ValueList.Count;
    ValueList = pcell->u.KeyNode.ValueList.List;
    Security = pcell->u.KeyNode.Security;

    //
    // Check simple non-empty cases
    //
    if (ClassLength > 0) {
        if( Class == HCELL_NIL ) {
            pcell->u.KeyNode.ClassLength = 0;
            HvMarkCellDirty(CmpCheckHive, Cell);
            KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx has ClassLength = %lu and Class == HCELL_NIL\n", CmpCheckHive, Cell,ClassLength));
        } else {
            if (HvIsCellAllocated(CmpCheckHive, Class) == FALSE) {
                    KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                    KdPrint(("\tClass:%08lx - unallocated class\n", Class));
                    rc = 4080;
                    CmpCheckKeyDebug.Status = rc;
                    return rc;
                } else {
                    SetUsed(CmpCheckHive, Class);
                }
        }
    }

    if (Security != HCELL_NIL) {
        if (HvIsCellAllocated(CmpCheckHive, Security) == FALSE) {
            KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
            KdPrint(("\tSecurity:%08lx - unallocated security\n", Security));
            rc = 4090;
            CmpCheckKeyDebug.Status = rc;
            return rc;
        } else if (HvGetCellType(Security) == Volatile) {
            SetUsed(CmpCheckHive, Security);
        }
        //
        // Else CmpValidateHiveSecurityDescriptors must do computation
        //
    }

    //
    // Check value list case
    //
    if (ValueCount > 0) {
        if (HvIsCellAllocated(CmpCheckHive, ValueList) == FALSE) {
            KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
            KdPrint(("\tValueList:%08lx - unallocated valuelist\n", ValueList));
            rc = 4100;
            CmpCheckKeyDebug.Status = rc;
            return rc;
        } else {
            SetUsed(CmpCheckHive, ValueList);
            pcell = HvGetCell(CmpCheckHive, ValueList);
            nrc = CmpCheckValueList(CmpCheckHive, pcell, ValueCount);
            if (nrc != 0) {
                KdPrint(("List was for CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                rc = nrc;
                CmpCheckKeyDebug.CellPoint = pcell;
                CmpCheckKeyDebug.Status = rc;
                return rc;
            }
        }
    }


    //
    // Check subkey list case
    //

    pcell = HvGetCell(CmpCheckHive, Cell);
    CmpCheckKeyDebug.CellPoint = pcell;
    if ((HvGetCellType(Cell) == Volatile) &&
        (pcell->u.KeyNode.SubKeyCounts[Stable] != 0))
    {
        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
        KdPrint(("\tVolatile Cell has Stable children\n"));
        rc = 4108;
        CmpCheckKeyDebug.Status = rc;
        return rc;
    } else if (pcell->u.KeyNode.SubKeyCounts[Stable] > 0) {
        if (! HvIsCellAllocated(CmpCheckHive, pcell->u.KeyNode.SubKeyLists[Stable])) {
            KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
            KdPrint(("\tStableKeyList:%08lx - unallocated\n", pcell->u.KeyNode.SubKeyLists[Stable]));
            rc = 4110;
            CmpCheckKeyDebug.Status = rc;
            return rc;
        } else {
            SetUsed(CmpCheckHive, pcell->u.KeyNode.SubKeyLists[Stable]);

            //
            // Prove that the index is OK
            //
            Root = (PCM_KEY_INDEX)HvGetCell(
                                    CmpCheckHive,
                                    pcell->u.KeyNode.SubKeyLists[Stable]
                                    );
            CmpCheckKeyDebug.RootPoint = Root;
            if ((Root->Signature == CM_KEY_INDEX_LEAF) ||
                (Root->Signature == CM_KEY_FAST_LEAF)) {
                if ((ULONG)Root->Count != pcell->u.KeyNode.SubKeyCounts[Stable]) {
                    KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                    KdPrint(("\tBad Index count @%08lx\n", Root));
                    rc = 4120;
                    CmpCheckKeyDebug.Status = rc;
                    return rc;
                }
            } else if (Root->Signature == CM_KEY_INDEX_ROOT) {
                SubCount = 0;
                for (i = 0; i < Root->Count; i++) {
                    CmpCheckKeyDebug.Index = i;
                    if (! HvIsCellAllocated(CmpCheckHive, Root->List[i])) {
                        KdPrint(("CmpCheckKey: Hive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                        KdPrint(("\tBad Leaf Cell %08lx Root@%08lx\n", Root->List[i], Root));
                        rc = 4130;
                        CmpCheckKeyDebug.Status = rc;
                        return rc;
                    }
                    Leaf = (PCM_KEY_INDEX)HvGetCell(CmpCheckHive,
                                                    Root->List[i]);
                    if ((Leaf->Signature != CM_KEY_INDEX_LEAF) &&
                        (Leaf->Signature != CM_KEY_FAST_LEAF)) {
                        KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                        KdPrint(("\tBad Leaf Index @%08lx Root@%08lx\n", Leaf, Root));
                        rc = 4140;
                        CmpCheckKeyDebug.Status = rc;
                        return rc;
                    }
                    SetUsed(CmpCheckHive, Root->List[i]);
                    SubCount += Leaf->Count;
                }
                if (pcell->u.KeyNode.SubKeyCounts[Stable] != SubCount) {
                    KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                    KdPrint(("\tBad count in index, SubCount=%08lx\n", SubCount));
                    rc = 4150;
                    CmpCheckKeyDebug.Status = rc;
                    return rc;
                }
            } else {
                KdPrint(("CmpCheckKey: CmpCheckHive:%08lx Cell:%08lx\n", CmpCheckHive, Cell));
                KdPrint(("\tBad Root index signature @%08lx\n", Root));
                rc = 4120;
                CmpCheckKeyDebug.Status = rc;
                return rc;
            }
        }
    }
    //
    // force volatiles to be empty, if this is a load operation
    //
    if (CmpCheckClean == TRUE) {
        pcell->u.KeyNode.SubKeyCounts[Volatile] = 0;
        pcell->u.KeyNode.SubKeyLists[Volatile] = HCELL_NIL;
    }

    return rc;
}
Ejemplo n.º 22
0
VALUE_SEARCH_RETURN_TYPE
CmpGetValueKeyFromCache(
    IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
    IN PCELL_DATA           List,
    IN ULONG                Index,
    OUT PPCM_CACHED_VALUE   *ContainingList,
    OUT PCM_KEY_VALUE       *Value,
    IN BOOLEAN              IndexCached,
    OUT BOOLEAN             *ValueCached,
    OUT PHCELL_INDEX        CellToRelease
)
/*++

Routine Description:

    Get the Valve Node.  Check if it is already cached, if not but the index is cached, 
    cache and return the value node.

Arguments:

    Hive - pointer to hive control structure for hive of interest.

    List - pointer to the Value Index Array (of ULONG_PTR if cached and ULONG if non-cached)

    Index - Index in the Value index array

    ContainlingList - The address of the entry that will receive the found cached value.

    IndexCached - Indicate if the index list is cached.  If not, everything is from the
                  original registry data.

    ValueCached - Indicating whether Value is cached or not.

Return Value:

    Pointer to the Value Node.

    NULL when we couldn't map a view 
--*/
{
    PULONG_PTR          CachedList;
    ULONG               AllocSize;
    ULONG               CopySize;
    PCM_CACHED_VALUE    CachedValue;
    PHHIVE              Hive;

    *CellToRelease = HCELL_NIL;
    Hive = KeyControlBlock->KeyHive;
    *Value = NULL;
    if (IndexCached) {
        //
        // The index array is cached, so List is pointing to an array of ULONG_PTR.
        // Use CachedList.
        //
        CachedList = (PULONG_PTR) List;
        *ValueCached = TRUE;
        if (CMP_IS_CELL_CACHED(CachedList[Index])) {
            *Value = CMP_GET_CACHED_KEYVALUE(CachedList[Index]);
            *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]);
        } else {
            //
            // ensure exclusive lock.
            //
            if( (CmpIsKCBLockedExclusive(KeyControlBlock) == FALSE) &&
                (CmpTryConvertKCBLockSharedToExclusive(KeyControlBlock) == FALSE) ) {
                //
                // need to upgrade lock to exclusive
                //
                return SearchNeedExclusiveLock;
            }
            *Value = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]);
            if( *Value == NULL ) {
                //
                // we couldn't map a view for this cell
                // just return NULL; the caller must handle it gracefully
                //
                return SearchFail;
            }
            *CellToRelease = List->u.KeyList[Index];

            //
            // Allocate a PagedPool to cache the value node.
            //
            CopySize = (ULONG) HvGetCellSize(Hive, *Value);
            AllocSize = CopySize + FIELD_OFFSET(CM_CACHED_VALUE, KeyValue);
            
            CachedValue = (PCM_CACHED_VALUE) ExAllocatePoolWithTag(PagedPool, AllocSize, CM_CACHE_VALUE_TAG);

            if (CachedValue) {
                //
                // Set the information for later use if we need to cache data as well.
                //
                if ((*Value)->Flags & VALUE_COMP_NAME) {
                    CachedValue->HashKey = CmpComputeHashKeyForCompressedName(0,(*Value)->Name,(*Value)->NameLength);
                } else {
                    UNICODE_STRING TmpStr;
                    TmpStr.Length = (*Value)->NameLength;
                    TmpStr.Buffer = (*Value)->Name;
                    CachedValue->HashKey = CmpComputeHashKey(0,&TmpStr
#if DBG
                                                             , TRUE
#endif
                        );
                }
                CachedValue->DataCacheType = CM_CACHE_DATA_NOT_CACHED;
                CachedValue->ValueKeySize = (USHORT) CopySize;

                RtlCopyMemory((PVOID)&(CachedValue->KeyValue), *Value, CopySize);


                // Trying to catch the BAD guy who writes over our pool.
                CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList) );

                CachedList[Index] = CMP_MARK_CELL_CACHED(CachedValue);

                // Trying to catch the BAD guy who writes over our pool.
                CmpMakeSpecialPoolReadOnly( CMP_GET_CACHED_ADDRESS(CachedList) );


                // Trying to catch the BAD guy who writes over our pool.
                CmpMakeSpecialPoolReadOnly(CachedValue);

                *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]);
                //
                // Now we have the stuff cached, use the cache data.
                //
                (*Value) = CMP_GET_CACHED_KEYVALUE(CachedValue);
            } else {
                //
                // If the allocation fails, just do not cache it. continue.
                //
                *ValueCached = FALSE;
            }
        }
    } else {
        //
        // The Valve Index Array is from the registry hive, just get the cell and move on.
        //
        (*Value) = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]);
        *ValueCached = FALSE;
        if( *Value == NULL ) {
            //
            // we couldn't map a view for this cell
            // just return NULL; the caller must handle it gracefully
            // OBS: we may remove this as we return pchild anyway; just for clarity
            //
            return SearchFail;
        }
        *CellToRelease = List->u.KeyList[Index];
    }
    return SearchSuccess;
}
Ejemplo n.º 23
0
VALUE_SEARCH_RETURN_TYPE
CmpGetValueListFromCache(
    IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
    OUT PCELL_DATA          *List,
    OUT BOOLEAN             *IndexCached,
    OUT PHCELL_INDEX        ValueListToRelease
)
/*++

Routine Description:

    Get the Valve Index Array.  Check if it is already cached, if not, cache it and return
    the cached entry.

Arguments:

    Hive - pointer to hive control structure for hive of interest

    ChildList - pointer/index to the Value Index array

    IndexCached - Indicating whether Value Index list is cached or not.

Return Value:

    Pointer to the Valve Index Array.

    NULL when we could not map view 

--*/
{
    HCELL_INDEX             CellToRelease;
    PCACHED_CHILD_LIST      ChildList;
    PHHIVE                  Hive;
#ifndef _WIN64
    ULONG                   AllocSize;
    PCM_CACHED_VALUE_INDEX  CachedValueIndex;
    ULONG                   i;
#endif
    ASSERT_KCB_LOCKED(KeyControlBlock);

    Hive = KeyControlBlock->KeyHive;
    ChildList = &(KeyControlBlock->ValueCache);
    *ValueListToRelease = HCELL_NIL;

#ifndef _WIN64
    *IndexCached = TRUE;
    if (CMP_IS_CELL_CACHED(ChildList->ValueList)) {
        //
        // The entry is already cached.
        //
        *List = CMP_GET_CACHED_CELLDATA(ChildList->ValueList);
    } else {
        //
        // The entry is not cached.  The element contains the hive index.
        // ensure exclusive lock.
        //
        if( (CmpIsKCBLockedExclusive(KeyControlBlock) == FALSE) &&
            (CmpTryConvertKCBLockSharedToExclusive(KeyControlBlock) == FALSE) ) {
            //
            // need to upgrade lock to exclusive
            //
            return SearchNeedExclusiveLock;
        }

        CellToRelease = CMP_GET_CACHED_CELL_INDEX(ChildList->ValueList);
        *List = (PCELL_DATA) HvGetCell(Hive, CellToRelease);
        if( *List == NULL ) {
            //
            // we couldn't map a view for this cell
            //
            *IndexCached = FALSE; 
            return SearchFail;
        }

        //
        // Allocate a PagedPool to cache the value index cell.
        //

        AllocSize = ChildList->Count * sizeof(ULONG_PTR) + FIELD_OFFSET(CM_CACHED_VALUE_INDEX, Data);
        CachedValueIndex = (PCM_CACHED_VALUE_INDEX) ExAllocatePoolWithTag(PagedPool, AllocSize, CM_CACHE_VALUE_INDEX_TAG);

        if (CachedValueIndex) {

            CachedValueIndex->CellIndex = CMP_GET_CACHED_CELL_INDEX(ChildList->ValueList);
#pragma prefast(suppress:12009, "no overflow")
            for (i=0; i<ChildList->Count; i++) {
                CachedValueIndex->Data.List[i] = (ULONG_PTR) (*List)->u.KeyList[i];
            }

            ChildList->ValueList = CMP_MARK_CELL_CACHED(CachedValueIndex);

            // Trying to catch the BAD guy who writes over our pool.
            CmpMakeSpecialPoolReadOnly( CachedValueIndex );

            //
            // Now we have the stuff cached, use the cache data.
            //
            *List = CMP_GET_CACHED_CELLDATA(ChildList->ValueList);
        } else {
            //
            // If the allocation fails, just do not cache it. continue.
            //
            *IndexCached = FALSE; 
        }
        *ValueListToRelease = CellToRelease;
    }
#else
    CellToRelease = CMP_GET_CACHED_CELL_INDEX(ChildList->ValueList);
    *List = (PCELL_DATA) HvGetCell(Hive, CellToRelease);
    *IndexCached = FALSE;
    if( *List == NULL ) {
        //
        // we couldn't map a view for this cell
        // OBS: we can drop this as we return List anyway; just for clarity
        //
        return SearchFail;
    }
    *ValueListToRelease = CellToRelease;
#endif

    return SearchSuccess;
}
Ejemplo n.º 24
0
NTSTATUS
NTAPI
CmpFreeKeyByCell(IN PHHIVE Hive,
                 IN HCELL_INDEX Cell,
                 IN BOOLEAN Unlink)
{
    PCELL_DATA CellData, ParentData, ListData;
    ULONG i;
    BOOLEAN Result;

    /* Mark the entire key dirty */
    CmpMarkKeyDirty(Hive, Cell ,TRUE);

    /* Get the target node and release it */
    CellData = HvGetCell(Hive, Cell);
    if (!CellData) ASSERT(FALSE);
    HvReleaseCell(Hive, Cell);

    /* Make sure we don't have subkeys */
    ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
            CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);

    /* Check if we have to unlink */
    if (Unlink)
    {
        /* Remove the subkey */
        Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
        if (!Result) return STATUS_INSUFFICIENT_RESOURCES;

        /* Get the parent node and release it */
        ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
        if (!ParentData) ASSERT(FALSE);
        HvReleaseCell(Hive, CellData->u.KeyNode.Parent);

        /* Check if the parent node has no more subkeys */
        if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
                ParentData->u.KeyNode.SubKeyCounts[Volatile]))
        {
            /* Then free the cached name/class lengths */
            ParentData->u.KeyNode.MaxNameLen = 0;
            ParentData->u.KeyNode.MaxClassLen = 0;
        }
    }

    /* Check if we have any values */
    if (CellData->u.KeyNode.ValueList.Count > 0)
    {
        /* Get the value list and release it */
        ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
        if (!ListData) ASSERT(FALSE);
        HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);

        /* Loop every value */
        for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
        {
            /* Free it */
            if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
        }

        /* Free the value list */
        HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
    }

    /* Free the key body itself, and then return our status */
    if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
    return STATUS_SUCCESS;
}
Ejemplo n.º 25
0
static
BOOLEAN
RegImportSubKey(
    PHHIVE Hive,
    PCM_KEY_NODE KeyCell,
    FRLDRHKEY ParentKey)
{
    PCM_KEY_INDEX IndexCell;
    PVALUE_LIST_CELL ValueListCell;
    PCM_KEY_VALUE ValueCell = NULL;
    PWCHAR wName;
    FRLDRHKEY SubKey;
    LONG Error;
    ULONG i;

    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;
    }

    if (KeyCell->Flags & KEY_COMP_NAME)
    {
        wName = MmHeapAlloc((KeyCell->NameLength + 1) * sizeof(WCHAR));
        for (i = 0; i < KeyCell->NameLength; i++)
        {
            wName[i] = ((PCHAR)KeyCell->Name)[i];
        }
        wName[KeyCell->NameLength] = 0;
    }
    else
    {
        wName = MmHeapAlloc(KeyCell->NameLength + sizeof(WCHAR));
        memcpy(wName, KeyCell->Name, KeyCell->NameLength);
        wName[KeyCell->NameLength / sizeof(WCHAR)] = 0;
    }

    TRACE("KeyName: '%S'\n", wName);

    /* Create new sub key */
    Error = RegCreateKey(ParentKey, wName, &SubKey);
    MmHeapFree(wName);
    if (Error != ERROR_SUCCESS)
    {
        ERR("RegCreateKey() failed!\n");
        return FALSE;
    }
    TRACE("Subkeys: %u\n", KeyCell->SubKeyCounts);
    TRACE("Values: %u\n", KeyCell->ValueList.Count);

    /* Enumerate and add values */
    if (KeyCell->ValueList.Count > 0)
    {
        ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyCell->ValueList.List);
        TRACE("ValueListCell: %x\n", ValueListCell);

        for (i = 0; i < KeyCell->ValueList.Count; i++)
        {
            TRACE("ValueOffset[%d]: %x\n", i, ValueListCell->ValueOffset[i]);

            ValueCell = (PCM_KEY_VALUE) HvGetCell (Hive, ValueListCell->ValueOffset[i]);

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

            if (!RegImportValue(Hive, ValueCell, SubKey))
                return FALSE;
        }
    }

    /* Enumerate and add subkeys */
    if (KeyCell->SubKeyCounts[Stable] > 0)
    {
        IndexCell = HvGetCell (Hive, KeyCell->SubKeyLists[Stable]);

        if (!RegImportIndexSubKey(Hive, IndexCell, SubKey))
            return FALSE;
    }

    return TRUE;
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
0
NTSTATUS
BiOpenKey(
    _In_ HANDLE ParentHandle,
    _In_ PWCHAR KeyName,
    _Out_ PHANDLE Handle
    )
{
    PBI_KEY_OBJECT ParentKey, NewKey;
    PBI_KEY_HIVE ParentHive;
    NTSTATUS Status;
    ULONG NameLength, SubNameLength, NameBytes;
    PWCHAR NameStart, NameBuffer;
    UNICODE_STRING KeyString;
    HCELL_INDEX KeyCell;
    PHHIVE Hive;
    PCM_KEY_NODE ParentNode;

    /* Convert from a handle to our key object */
    ParentKey = (PBI_KEY_OBJECT)ParentHandle;

    /* Extract the hive and node information */
    ParentHive = ParentKey->KeyHive;
    ParentNode = ParentKey->KeyNode;
    Hive = &ParentKey->KeyHive->Hive.Hive;

    /* Initialize variables */
    KeyCell = HCELL_NIL;
    Status = STATUS_SUCCESS;
    NameBuffer = NULL;

    /* Loop as long as there's still portions of the key name in play */
    NameLength = wcslen(KeyName);
    while (NameLength)
    {
        /* Find the first path separator */
        NameStart = wcschr(KeyName, OBJ_NAME_PATH_SEPARATOR);
        if (NameStart)
        {
            /* Look only at the key before the separator */
            SubNameLength = NameStart - KeyName;
            ++NameStart;
        }
        else
        {
            /* No path separator, this is the final leaf key */
            SubNameLength = NameLength;
        }

        /* Free the name buffer from the previous pass if needed */
        if (NameBuffer)
        {
            BlMmFreeHeap(NameBuffer);
        }

        /* Allocate a buffer to hold the name of this specific subkey only */
        NameBytes = SubNameLength * sizeof(WCHAR);
        NameBuffer = BlMmAllocateHeap(NameBytes + sizeof(UNICODE_NULL));
        if (!NameBuffer)
        {
            Status = STATUS_NO_MEMORY;
            goto Quickie;
        }

        /* Copy and null-terminate the name of the subkey */
        RtlCopyMemory(NameBuffer, KeyName, NameBytes);
        NameBuffer[SubNameLength] = UNICODE_NULL;

        /* Convert it into a UNICODE_STRING and try to find it */
        RtlInitUnicodeString(&KeyString, NameBuffer);
        KeyCell = CmpFindSubKeyByName(Hive, ParentNode, &KeyString);
        if (KeyCell == HCELL_NIL)
        {
            Status = STATUS_OBJECT_NAME_NOT_FOUND;
            goto Quickie;
        }

        /* We found it -- get the key node out of it */
        ParentNode = (PCM_KEY_NODE)HvGetCell(Hive, KeyCell);
        if (!ParentNode)
        {
            Status = STATUS_REGISTRY_CORRUPT;
            goto Quickie;
        }

        /* Update the key name to the next remaining path element */
        KeyName = NameStart;
        if (NameStart)
        {
            /* Update the length to the remainder of the path */
            NameLength += -1 - SubNameLength;
        }
        else
        {
            /* There's nothing left, this was the leaf key */
            NameLength = 0;
        }
    }

    /* Allocate a key object */
    NewKey = BlMmAllocateHeap(sizeof(*NewKey));
    if (!NewKey)
    {
        /* Bail out if we had no memory for it */
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Fill out the key object data */
    NewKey->KeyNode = ParentNode;
    NewKey->KeyHive = ParentHive;
    NewKey->KeyName = NameBuffer;
    NewKey->KeyCell = KeyCell;

    /* Add a reference to the hive */
    ++ParentHive->ReferenceCount;

    /* Return the object back to the caller */
    *Handle = NewKey;

Quickie:
    /* If we had a name buffer, free it */
    if (NameBuffer)
    {
        BlMmFreeHeap(NameBuffer);
    }

    /* Return status of the open operation */
    return Status;
}
Ejemplo n.º 29
0
BOOLEAN
NTAPI
CmpMarkKeyDirty(IN PHHIVE Hive,
                IN HCELL_INDEX Cell,
                IN BOOLEAN CheckNoSubkeys)
{
    PCELL_DATA CellData, ListData, SecurityData, ValueData;
    ULONG i;

    /* Get the cell data for our target */
    CellData = HvGetCell(Hive, Cell);
    if (!CellData) return FALSE;

    /* Check if sanity checks requested */
    if (CheckNoSubkeys)
    {
        /* Do them */
        ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
        ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
    }

    /* If this is an exit hive, there's nothing to do */
    if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
    {
        /* Release the cell and get out */
        HvReleaseCell(Hive, Cell);
        return TRUE;
    }

    /* Otherwise, mark it dirty and release it */
    HvMarkCellDirty(Hive, Cell, FALSE);
    HvReleaseCell(Hive, Cell);

    /* Check if we have a class */
    if (CellData->u.KeyNode.Class != HCELL_NIL)
    {
        /* Mark it dirty */
        HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
    }

    /* Check if we have security */
    if (CellData->u.KeyNode.Security != HCELL_NIL)
    {
        /* Mark it dirty */
        HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);

        /* Get the security data and release it */
        SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
        if (!SecurityData) ASSERT(FALSE);
        HvReleaseCell(Hive, CellData->u.KeyNode.Security);

        /* Mark the security links dirty too */
        HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
        HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
    }

    /* Check if we have any values */
    if (CellData->u.KeyNode.ValueList.Count > 0)
    {
        /* Dirty the value list */
        HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);

        /* Get the list data itself, and release it */
        ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
        if (!ListData) ASSERT(FALSE);
        HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);

        /* Loop all values */
        for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
        {
            /* Dirty each value */
            HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);

            /* Get the value data and release it */
            ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
            ASSERT(ValueData);
            HvReleaseCell(Hive,ListData->u.KeyList[i]);

            /* Mark the value data dirty too */
            if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
            {
                /* Failure */
                return FALSE;
            }
        }
    }

    /* If this is an entry hive, we're done */
    if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;

    /* Otherwise mark the index dirty too */
    if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
    {
        /* Failure */
        return FALSE;
    }

    /* Finally, mark the parent dirty */
    HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
    return TRUE;
}
Ejemplo n.º 30
0
static
BOOLEAN
RegImportValue (
    PHHIVE Hive,
    PCM_KEY_VALUE ValueCell,
    FRLDRHKEY Key)
{
    PVOID DataCell;
    PWCHAR wName;
    LONG Error;
    ULONG DataLength;
    ULONG i;

    if (ValueCell->Signature != CM_KEY_VALUE_SIGNATURE)
    {
        ERR("Invalid key cell!\n");
        return FALSE;
    }

    if (ValueCell->Flags & VALUE_COMP_NAME)
    {
        wName = MmHeapAlloc ((ValueCell->NameLength + 1) * sizeof(WCHAR));
        for (i = 0; i < ValueCell->NameLength; i++)
        {
            wName[i] = ((PCHAR)ValueCell->Name)[i];
        }
        wName[ValueCell->NameLength] = 0;
    }
    else
    {
        wName = MmHeapAlloc(ValueCell->NameLength + sizeof(WCHAR));
        memcpy(wName, ValueCell->Name, ValueCell->NameLength);
        wName[ValueCell->NameLength / sizeof(WCHAR)] = 0;
    }

    DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK;

    TRACE("ValueName: '%S'\n", wName);
    TRACE("DataLength: %u\n", DataLength);

    if (DataLength <= sizeof(HCELL_INDEX) && (ValueCell->DataLength & REG_DATA_IN_OFFSET))
    {
        Error = RegSetValue(Key,
                            wName,
                            ValueCell->Type,
                            (PCHAR)&ValueCell->Data,
                            DataLength);
        if (Error != ERROR_SUCCESS)
        {
            ERR("RegSetValue() failed!\n");
            MmHeapFree(wName);
            return FALSE;
        }
    }
    else
    {
        DataCell = (PVOID)HvGetCell(Hive, ValueCell->Data);
        TRACE("DataCell: %x\n", DataCell);

        Error = RegSetValue(Key,
                            wName,
                            ValueCell->Type,
                            DataCell,
                            DataLength);

        if (Error != ERROR_SUCCESS)
        {
            ERR("RegSetValue() failed!\n");
            MmHeapFree(wName);
            return FALSE;
        }
    }

    MmHeapFree(wName);

    return TRUE;
}