Example #1
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;
}
Example #2
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;
}
Example #3
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;
}
Example #4
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;
}
Example #5
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;
}
Example #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;
}