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