Exemple #1
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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
0
LONG WINAPI
RegSetValueExW(
	IN HKEY hKey,
	IN LPCWSTR lpValueName OPTIONAL,
	IN ULONG Reserved,
	IN ULONG dwType,
	IN const UCHAR* lpData,
	IN USHORT cbData)
{
	MEMKEY Key, DestKey;
	PHKEY phKey;
	PCM_KEY_VALUE ValueCell;
	HCELL_INDEX ValueCellOffset;
	PVOID DataCell;
	LONG DataCellSize;
	NTSTATUS Status;

	if (dwType == REG_LINK)
	{
		/* Special handling of registry links */
		if (cbData != sizeof(PVOID))
			return STATUS_INVALID_PARAMETER;
		phKey = (PHKEY)lpData;
		Key = HKEY_TO_MEMKEY(hKey);
		DestKey = HKEY_TO_MEMKEY(*phKey);

		/* Create the link in memory */
		Key->DataType = REG_LINK;
		Key->LinkedKey = DestKey;

		/* Create the link in registry hive (if applicable) */
		if (Key->RegistryHive != DestKey->RegistryHive)
			return STATUS_SUCCESS;
		DPRINT1("Save link to registry\n");
		return STATUS_NOT_IMPLEMENTED;
	}

	if ((cbData & REG_DATA_SIZE_MASK) != cbData)
		return STATUS_UNSUCCESSFUL;

	Key = HKEY_TO_MEMKEY(hKey);

	Status = RegpOpenOrCreateValue(hKey, lpValueName, TRUE, &ValueCell, &ValueCellOffset);
	if (!NT_SUCCESS(Status))
		return ERROR_UNSUCCESSFUL;

	/* Get size of the allocated cellule (if any) */
	if (!(ValueCell->DataLength & REG_DATA_IN_OFFSET) &&
		(ValueCell->DataLength & REG_DATA_SIZE_MASK) != 0)
	{
		DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->Data);
		if (!DataCell)
			return ERROR_UNSUCCESSFUL;
		DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell);
	}
	else
	{
		DataCell = NULL;
		DataCellSize = 0;
	}

	if (cbData <= sizeof(HCELL_INDEX))
	{
		/* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
		DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
		if (DataCell)
			HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);

		RtlCopyMemory(&ValueCell->Data, lpData, cbData);
		ValueCell->DataLength = (ULONG)(cbData | REG_DATA_IN_OFFSET);
		ValueCell->Type = dwType;
		HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
	}
	else
	{
		if (cbData > (SIZE_T)DataCellSize)
		{
			/* New data size is larger than the current, destroy current
			 * data block and allocate a new one. */
			HCELL_INDEX NewOffset;

			DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);

			NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, Stable, HCELL_NIL);
			if (NewOffset == HCELL_NIL)
			{
				DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status);
				return ERROR_UNSUCCESSFUL;
			}

			if (DataCell)
				HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);

			ValueCell->Data = NewOffset;
			DataCell = (PVOID)HvGetCell(&Key->RegistryHive->Hive, NewOffset);
		}

		/* Copy new contents to cellule */
		RtlCopyMemory(DataCell, lpData, cbData);
		ValueCell->DataLength = (ULONG)(cbData & REG_DATA_SIZE_MASK);
		ValueCell->Type = dwType;
		HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->Data, FALSE);
		HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
	}

	HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE);

	DPRINT("Return status 0x%08x\n", Status);
	return Status;
}
Exemple #5
0
NTSTATUS
CmiAddValueKey(
	IN PCMHIVE RegistryHive,
	IN PCM_KEY_NODE KeyCell,
	IN HCELL_INDEX KeyCellOffset,
	IN PCUNICODE_STRING ValueName,
	OUT PCM_KEY_VALUE *pValueCell,
	OUT HCELL_INDEX *pValueCellOffset)
{
	PVALUE_LIST_CELL ValueListCell;
	PCM_KEY_VALUE NewValueCell;
	HCELL_INDEX ValueListCellOffset;
	HCELL_INDEX NewValueCellOffset;
	ULONG CellSize;
	HSTORAGE_TYPE Storage;
	NTSTATUS Status;

	Storage = (KeyCell->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
	if (KeyCell->ValueList.List == HCELL_NIL)
	{
		/* Allocate some room for the value list */
		CellSize = sizeof(VALUE_LIST_CELL) + (3 * sizeof(HCELL_INDEX));
		ValueListCellOffset = HvAllocateCell(&RegistryHive->Hive, CellSize, Storage, HCELL_NIL);
		if (ValueListCellOffset == HCELL_NIL)
			return STATUS_INSUFFICIENT_RESOURCES;

		ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
		if (!ValueListCell)
			return STATUS_UNSUCCESSFUL;
		KeyCell->ValueList.List = ValueListCellOffset;
		HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
	}
	else
	{
		ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
		if (!ValueListCell)
			return STATUS_UNSUCCESSFUL;
		CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));

		if (KeyCell->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
		{
			CellSize *= 2;
			ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, KeyCell->ValueList.List, CellSize);
			if (ValueListCellOffset == HCELL_NIL)
				return STATUS_INSUFFICIENT_RESOURCES;

			ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
			if (!ValueListCell)
				return STATUS_UNSUCCESSFUL;
			KeyCell->ValueList.List = ValueListCellOffset;
			HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
        }
	}

	Status = CmiAllocateValueCell(
		RegistryHive,
		&NewValueCell,
		&NewValueCellOffset,
		ValueName,
		Storage);
	if (!NT_SUCCESS(Status))
		return Status;

	ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset;
	KeyCell->ValueList.Count++;
	if (NewValueCell->Flags & VALUE_COMP_NAME)
	{
	    if (NewValueCell->NameLength*sizeof(WCHAR) > KeyCell->MaxValueNameLen)
            KeyCell->MaxValueNameLen = NewValueCell->NameLength*sizeof(WCHAR);
	}
	else
	{
	    if (NewValueCell->NameLength > KeyCell->MaxValueNameLen)
            KeyCell->MaxValueNameLen = NewValueCell->NameLength;
	}

	HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
	HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List, FALSE);
	HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset, FALSE);

	*pValueCell = NewValueCell;
	*pValueCellOffset = NewValueCellOffset;

	return STATUS_SUCCESS;
}
Exemple #6
0
NTSTATUS
CmiAddSubKey(
	IN PCMHIVE RegistryHive,
	IN PCM_KEY_NODE ParentKeyCell,
	IN HCELL_INDEX ParentKeyCellOffset,
	IN PCUNICODE_STRING SubKeyName,
	IN ULONG CreateOptions,
	OUT PCM_KEY_NODE *pSubKeyCell,
	OUT HCELL_INDEX *pBlockOffset)
{
	PCM_KEY_FAST_INDEX HashBlock;
	HCELL_INDEX NKBOffset;
	PCM_KEY_NODE NewKeyCell;
	ULONG NewBlockSize;
	NTSTATUS Status;
	USHORT NameLength;
	PWSTR NamePtr;
	BOOLEAN Packable;
	HSTORAGE_TYPE Storage;
	ULONG i;

	VERIFY_KEY_CELL(ParentKeyCell);

	/* Skip leading backslash */
	if (SubKeyName->Buffer[0] == L'\\')
	{
		NamePtr = &SubKeyName->Buffer[1];
		NameLength = SubKeyName->Length - sizeof(WCHAR);
	}
	else
	{
		NamePtr = SubKeyName->Buffer;
		NameLength = SubKeyName->Length;
	}

	/* Check whether key name can be packed */
	Packable = TRUE;
	for (i = 0; i < NameLength / sizeof(WCHAR); i++)
	{
		if (NamePtr[i] & 0xFF00)
		{
			Packable = FALSE;
			break;
		}
	}

	/* Adjust name size */
	if (Packable)
	{
		NameLength = NameLength / sizeof(WCHAR);
	}

	Status = STATUS_SUCCESS;

	Storage = (CreateOptions & REG_OPTION_VOLATILE) ? Volatile : Stable;
	NewBlockSize = FIELD_OFFSET(CM_KEY_NODE, Name) + NameLength;
	NKBOffset = HvAllocateCell(&RegistryHive->Hive, NewBlockSize, Storage, HCELL_NIL);
	if (NKBOffset == HCELL_NIL)
	{
		Status = STATUS_INSUFFICIENT_RESOURCES;
	}
	else
	{
		NewKeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, NKBOffset);
		NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE;
		if (CreateOptions & REG_OPTION_VOLATILE)
		{
			NewKeyCell->Flags = KEY_IS_VOLATILE;
		}
		else
		{
			NewKeyCell->Flags = 0;
		}
		KeQuerySystemTime(&NewKeyCell->LastWriteTime);
		NewKeyCell->Parent = ParentKeyCellOffset;
		NewKeyCell->SubKeyCounts[Stable] = 0;
		NewKeyCell->SubKeyCounts[Volatile] = 0;
		NewKeyCell->SubKeyLists[Stable] = HCELL_NIL;
		NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL;
		NewKeyCell->ValueList.Count = 0;
		NewKeyCell->ValueList.List = HCELL_NIL;
		NewKeyCell->Security = HCELL_NIL;
		NewKeyCell->Class = HCELL_NIL;

		/* Pack the key name */
		NewKeyCell->NameLength = NameLength;
		if (Packable)
		{
			NewKeyCell->Flags |= KEY_COMP_NAME;
			for (i = 0; i < NameLength; i++)
			{
				((PCHAR)NewKeyCell->Name)[i] = (CHAR)(NamePtr[i] & 0x00FF);
			}
		}
		else
		{
			RtlCopyMemory(
				NewKeyCell->Name,
				NamePtr,
				NameLength);
		}

		VERIFY_KEY_CELL(NewKeyCell);
	}

	if (!NT_SUCCESS(Status))
	{
		return Status;
	}

	if (ParentKeyCell->SubKeyLists[Storage] == HCELL_NIL)
	{
		Status = CmiAllocateHashTableCell (
			RegistryHive,
			&HashBlock,
			&ParentKeyCell->SubKeyLists[Storage],
			REG_INIT_HASH_TABLE_SIZE,
			Storage);
		if (!NT_SUCCESS(Status))
		{
			return(Status);
		}
	}
	else
	{
		HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (
			&RegistryHive->Hive,
			ParentKeyCell->SubKeyLists[Storage]);
		ASSERT(HashBlock->Signature == CM_KEY_FAST_LEAF);

		if (HashBlock->Count ==
		    ((HvGetCellSize(&RegistryHive->Hive, HashBlock) - FIELD_OFFSET(CM_KEY_FAST_INDEX, List)) / sizeof(CM_INDEX)))
		{
			PCM_KEY_FAST_INDEX NewHashBlock;
			HCELL_INDEX HTOffset;

			/* Reallocate the hash table cell */
			Status = CmiAllocateHashTableCell (
				RegistryHive,
				&NewHashBlock,
				&HTOffset,
				HashBlock->Count +
				REG_EXTEND_HASH_TABLE_SIZE,
				Storage);
			if (!NT_SUCCESS(Status))
			{
				return Status;
			}
			RtlCopyMemory(
				&NewHashBlock->List[0],
				&HashBlock->List[0],
				sizeof(NewHashBlock->List[0]) * HashBlock->Count);
         NewHashBlock->Count = HashBlock->Count;
			HvFreeCell (&RegistryHive->Hive, ParentKeyCell->SubKeyLists[Storage]);
			ParentKeyCell->SubKeyLists[Storage] = HTOffset;
			HashBlock = NewHashBlock;
		}
	}

	Status = CmiAddKeyToHashTable(
		RegistryHive,
		HashBlock,
      ParentKeyCell->SubKeyLists[Storage],
		NewKeyCell,
		NKBOffset);
	if (NT_SUCCESS(Status))
	{
		ParentKeyCell->SubKeyCounts[Storage]++;
		if (Packable)
        {
            if (NameLength*sizeof(WCHAR) > ParentKeyCell->MaxNameLen)
                ParentKeyCell->MaxNameLen = NameLength*sizeof(WCHAR);
        }
        else
        {
            if (NameLength > ParentKeyCell->MaxNameLen)
                ParentKeyCell->MaxNameLen = NameLength;
        }
        if (NewKeyCell->ClassLength > ParentKeyCell->MaxClassLen)
            ParentKeyCell->MaxClassLen = NewKeyCell->ClassLength;

		*pSubKeyCell = NewKeyCell;
		*pBlockOffset = NKBOffset;
	}

	KeQuerySystemTime(&ParentKeyCell->LastWriteTime);
	HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE);

	return Status;
}