ReactOS 0.4.15-dev-8093-g3285f69
cmapi.c File Reference
#include "ntoskrnl.h"
#include "debug.h"
Include dependency graph for cmapi.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

BOOLEAN NTAPI CmpIsHiveAlreadyLoaded (IN HANDLE KeyHandle, IN POBJECT_ATTRIBUTES SourceFile, OUT PCMHIVE *CmHive)
 
BOOLEAN NTAPI CmpDoFlushAll (IN BOOLEAN ForceFlush)
 
NTSTATUS NTAPI CmpSetValueKeyNew (IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PUNICODE_STRING ValueName, IN ULONG Index, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG SmallData)
 
NTSTATUS NTAPI CmpSetValueKeyExisting (IN PHHIVE Hive, IN HCELL_INDEX OldChild, IN PCM_KEY_VALUE Value, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG TempData)
 
NTSTATUS NTAPI CmpQueryKeyData (IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN KEY_INFORMATION_CLASS KeyInformationClass, IN OUT PVOID KeyInformation, IN ULONG Length, IN OUT PULONG ResultLength)
 
NTSTATUS NTAPI CmSetValueKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataLength)
 
NTSTATUS NTAPI CmDeleteValueKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN UNICODE_STRING ValueName)
 
NTSTATUS NTAPI CmQueryValueKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN UNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
 
NTSTATUS NTAPI CmEnumerateValueKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
 
static NTSTATUS CmpQueryKeyDataFromCache (_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
 
static NTSTATUS CmpQueryFlagsInformation (_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo, _In_ ULONG Length, _In_ PULONG ResultLength)
 
static NTSTATUS CmpQueryNameInformation (_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
 
NTSTATUS NTAPI CmQueryKey (_In_ PCM_KEY_CONTROL_BLOCK Kcb, _In_ KEY_INFORMATION_CLASS KeyInformationClass, _Out_opt_ PVOID KeyInformation, _In_ ULONG Length, _Out_ PULONG ResultLength)
 
NTSTATUS NTAPI CmEnumerateKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
 
NTSTATUS NTAPI CmDeleteKey (IN PCM_KEY_BODY KeyBody)
 
NTSTATUS NTAPI CmFlushKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN ExclusiveLock)
 
NTSTATUS NTAPI CmLoadKey (IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, IN PCM_KEY_BODY KeyBody)
 
static BOOLEAN NTAPI CmpUnlinkHiveFromMaster (IN PCMHIVE CmHive, IN HCELL_INDEX Cell)
 
NTSTATUS NTAPI CmUnloadKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN ULONG Flags)
 
ULONG NTAPI CmpEnumerateOpenSubKeys (_In_ PCM_KEY_CONTROL_BLOCK RootKcb, _In_ BOOLEAN LockHeldExclusively, _In_ BOOLEAN RemoveEmptyCacheEntries, _In_ BOOLEAN DereferenceOpenedEntries)
 
static NTSTATUS CmpDeepCopyKeyInternal (IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HCELL_INDEX Parent, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
 
NTSTATUS NTAPI CmpDeepCopyKey (IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
 
NTSTATUS NTAPI CmSaveKey (IN PCM_KEY_CONTROL_BLOCK Kcb, IN HANDLE FileHandle, IN ULONG Flags)
 
NTSTATUS NTAPI CmSaveMergedKeys (IN PCM_KEY_CONTROL_BLOCK HighKcb, IN PCM_KEY_CONTROL_BLOCK LowKcb, IN HANDLE FileHandle)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file cmapi.c.

Function Documentation

◆ CmDeleteKey()

NTSTATUS NTAPI CmDeleteKey ( IN PCM_KEY_BODY  KeyBody)

Definition at line 1823 of file cmapi.c.

1824{
1826 PHHIVE Hive;
1828 HCELL_INDEX Cell, ParentCell;
1830
1831 /* Acquire hive lock */
1833
1834 /* Get the kcb */
1835 Kcb = KeyBody->KeyControlBlock;
1836
1837 /* Don't allow deleting the root */
1838 if (!Kcb->ParentKcb)
1839 {
1840 /* Fail */
1842 return STATUS_CANNOT_DELETE;
1843 }
1844
1845 /* Lock parent and child */
1847
1848 /* Check if we're already being deleted */
1849 if (Kcb->Delete)
1850 {
1851 /* Don't do it twice */
1853 goto Quickie;
1854 }
1855
1856 /* Get the hive and node */
1857 Hive = Kcb->KeyHive;
1858 Cell = Kcb->KeyCell;
1859
1860 /* Lock flushes */
1862
1863 /* Get the key node */
1864 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1865 ASSERT(Node);
1866
1867 /* Sanity check */
1868 ASSERT(Node->Flags == Kcb->Flags);
1869
1870 /* Check if we don't have any children */
1871 if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) &&
1872 !(Node->Flags & KEY_NO_DELETE))
1873 {
1874 /* Send notification to registered callbacks */
1875 CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
1876
1877 /* Get the parent and free the cell */
1878 ParentCell = Node->Parent;
1879 Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
1880 if (NT_SUCCESS(Status))
1881 {
1882 /* Flush any notifications */
1884
1885 /* Clean up information we have on the subkey */
1887
1888 /* Get the parent node */
1889 Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
1890 if (Parent)
1891 {
1892 /* Update the maximum name length */
1893 Kcb->ParentKcb->KcbMaxNameLen = (USHORT)Parent->MaxNameLen;
1894
1895 /* Make sure we're dirty */
1896 ASSERT(HvIsCellDirty(Hive, ParentCell));
1897
1898 /* Update the write time */
1899 KeQuerySystemTime(&Parent->LastWriteTime);
1900 Kcb->ParentKcb->KcbLastWriteTime = Parent->LastWriteTime;
1901
1902 /* Release the cell */
1903 HvReleaseCell(Hive, ParentCell);
1904 }
1905
1906 /* Set the KCB in delete mode and remove it */
1907 Kcb->Delete = TRUE;
1909
1910 /* Clear the cell */
1911 Kcb->KeyCell = HCELL_NIL;
1912 }
1913 }
1914 else
1915 {
1916 /* Fail */
1918 }
1919
1920 /* Release the cell */
1921 HvReleaseCell(Hive, Cell);
1922
1923 /* Release flush lock */
1925
1926 /* Release the KCB locks */
1927Quickie:
1928 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
1929
1930 /* Release hive lock */
1932 return Status;
1933}
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
LONG NTSTATUS
Definition: precomp.h:26
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_NO_DELETE
Definition: cmdata.h:33
VOID NTAPI CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeld)
Definition: cmkcbncb.c:1368
VOID NTAPI CmpCleanUpSubKeyInfo(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:517
VOID NTAPI CmpRemoveKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:306
NTSTATUS NTAPI CmpFreeKeyByCell(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN BOOLEAN Unlink)
Definition: cmkeydel.c:159
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:460
BOOLEAN CMAPI HvIsCellDirty(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:153
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
VOID NTAPI CmpReportNotify(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PHHIVE Hive, IN HCELL_INDEX Cell, IN ULONG Filter)
Definition: cmnotify.c:19
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:2056
VOID NTAPI CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2079
VOID NTAPI CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2108
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1970
VOID NTAPI CmpLockHiveFlusherShared(IN PCMHIVE Hive)
Definition: cmsysini.c:2017
VOID NTAPI CmpUnlockHiveFlusher(IN PCMHIVE Hive)
Definition: cmsysini.c:2028
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union node Node
Definition: types.h:1255
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
Status
Definition: gdiplustypes.h:25
@ Volatile
Definition: hivedata.h:128
@ Stable
Definition: hivedata.h:127
#define HCELL_NIL
Definition: hivedata.h:110
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define ASSERT(a)
Definition: mode.c:44
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cmlib.h:316
PHHIVE KeyHive
Definition: cm.h:285
struct _CM_KEY_CONTROL_BLOCK * ParentKcb
Definition: cm.h:289
HCELL_INDEX KeyCell
Definition: cm.h:286
Definition: dlist.c:348
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38

Referenced by NtDeleteKey().

◆ CmDeleteValueKey()

NTSTATUS NTAPI CmDeleteValueKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN UNICODE_STRING  ValueName 
)

Definition at line 915 of file cmapi.c.

917{
919 PHHIVE Hive;
921 HCELL_INDEX ChildCell, Cell;
924 ULONG ChildIndex;
926
927 /* Acquire hive lock */
929
930 /* Lock KCB exclusively */
932
933 /* Don't touch deleted keys */
934 if (Kcb->Delete)
935 {
936 /* Undo everything */
939 return STATUS_KEY_DELETED;
940 }
941
942 /* Get the hive and the cell index */
943 Hive = Kcb->KeyHive;
944 Cell = Kcb->KeyCell;
945
946 /* Lock flushes */
948
949 /* Get the parent key node */
950 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
951 ASSERT(Parent);
952
953 /* Get the value list and check if it has any entries */
954 ChildList = &Parent->ValueList;
955 if (ChildList->Count)
956 {
957 /* Try to find this value */
959 ChildList,
960 &ValueName,
961 &ChildIndex,
962 &ChildCell);
963 if (!Result)
964 {
965 /* Fail */
967 goto Quickie;
968 }
969
970 /* Value not found, return error */
971 if (ChildCell == HCELL_NIL) goto Quickie;
972
973 /* We found the value, mark all relevant cells dirty */
974 if (!(HvMarkCellDirty(Hive, Cell, FALSE) &&
975 HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE) &&
976 HvMarkCellDirty(Hive, ChildCell, FALSE)))
977 {
978 /* Not enough log space, fail */
980 goto Quickie;
981 }
982
983 /* Get the key value */
984 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ChildCell);
985 ASSERT(Value);
986
987 /* Mark it and all related data as dirty */
988 if (!CmpMarkValueDataDirty(Hive, Value))
989 {
990 /* Not enough log space, fail */
992 goto Quickie;
993 }
994
995 /* Sanity checks */
996 ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
997 ASSERT(HvIsCellDirty(Hive, ChildCell));
998
999 /* Remove the value from the child list */
1000 Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 /* Set known error */
1005 goto Quickie;
1006 }
1007
1008 /* Remove the value and its data itself */
1009 if (!CmpFreeValue(Hive, ChildCell))
1010 {
1011 /* Failed to free the value, fail */
1013 goto Quickie;
1014 }
1015
1016 /* Set the last write time */
1017 KeQuerySystemTime(&Parent->LastWriteTime);
1018 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
1019
1020 /* Sanity check */
1021 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1022 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1023 ASSERT(HvIsCellDirty(Hive, Cell));
1024
1025 /* Check if the value list is empty now */
1026 if (!Parent->ValueList.Count)
1027 {
1028 /* Then clear key node data */
1029 Parent->MaxValueNameLen = 0;
1030 Parent->MaxValueDataLen = 0;
1031 Kcb->KcbMaxValueNameLen = 0;
1032 Kcb->KcbMaxValueDataLen = 0;
1033 }
1034
1035 /* Cleanup the value cache */
1037
1038 /* Sanity checks */
1039 ASSERT(!CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList));
1040 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
1041
1042 /* Set the value cache */
1043 Kcb->ValueCache.Count = ChildList->Count;
1044 Kcb->ValueCache.ValueList = ChildList->List;
1045
1046 /* Notify registered callbacks */
1048
1049 /* Change default Status to success */
1051 }
1052
1053Quickie:
1054 /* Release the parent cell, if any */
1055 if (Parent) HvReleaseCell(Hive, Cell);
1056
1057 /* Check if we had a value */
1058 if (Value)
1059 {
1060 /* Release the child cell */
1061 ASSERT(ChildCell != HCELL_NIL);
1062 HvReleaseCell(Hive, ChildCell);
1063 }
1064
1065 /* Release locks */
1067 CmpReleaseKcbLock(Kcb);
1069 return Status;
1070}
unsigned char BOOLEAN
#define CM_KCB_SYM_LINK_FOUND
Definition: cm.h:55
FORCEINLINE VOID CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:116
#define CMP_IS_CELL_CACHED(c)
Definition: cm_x.h:34
FORCEINLINE VOID CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cm_x.h:185
struct _CM_KEY_VALUE * PCM_KEY_VALUE
VOID NTAPI CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:431
BOOLEAN NTAPI CmpMarkValueDataDirty(IN PHHIVE Hive, IN PCM_KEY_VALUE Value)
Definition: cmvalue.c:19
BOOLEAN NTAPI CmpFreeValue(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmvalue.c:73
NTSTATUS NTAPI CmpRemoveValueFromList(IN PHHIVE Hive, IN ULONG Index, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:320
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
Definition: hivecell.c:109
BOOLEAN NTAPI CmpFindNameInList(IN PHHIVE Hive, IN PCHILD_LIST ChildList, IN PCUNICODE_STRING Name, OUT PULONG ChildIndex OPTIONAL, OUT PHCELL_INDEX CellIndex)
Definition: cmname.c:149
#define NULL
Definition: types.h:112
#define STATUS_KEY_DELETED
Definition: ntstatus.h:613
#define STATUS_NO_LOG_SPACE
Definition: ntstatus.h:614
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFCHILDLIST * ChildList
Definition: wdfchildlist.h:481
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

Referenced by NtDeleteValueKey().

◆ CmEnumerateKey()

NTSTATUS NTAPI CmEnumerateKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN ULONG  Index,
IN KEY_INFORMATION_CLASS  KeyInformationClass,
IN PVOID  KeyInformation,
IN ULONG  Length,
IN PULONG  ResultLength 
)

Definition at line 1734 of file cmapi.c.

1740{
1742 PHHIVE Hive;
1744 HCELL_INDEX ChildCell;
1745 HV_TRACK_CELL_REF CellReferences = {0};
1746
1747 /* Acquire hive lock */
1749
1750 /* Lock the KCB shared */
1752
1753 /* Don't touch deleted keys */
1754 if (Kcb->Delete)
1755 {
1756 /* Undo everything */
1758 goto Quickie;
1759 }
1760
1761 /* Get the hive and parent */
1762 Hive = Kcb->KeyHive;
1763 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1764 ASSERT(Parent);
1765
1766 /* Get the child cell */
1767 ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
1768
1769 /* Release the parent cell */
1770 HvReleaseCell(Hive, Kcb->KeyCell);
1771
1772 /* Check if we found the child */
1773 if (ChildCell == HCELL_NIL)
1774 {
1775 /* We didn't, fail */
1777 goto Quickie;
1778 }
1779
1780 /* Now get the actual child node */
1781 Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
1782 ASSERT(Child);
1783
1784 /* Track references */
1785 if (!HvTrackCellRef(&CellReferences, Hive, ChildCell))
1786 {
1787 /* Can't allocate memory for tracking */
1789 goto Quickie;
1790 }
1791
1792 /* Data can be user-mode, use SEH */
1793 _SEH2_TRY
1794 {
1795 /* Query the data requested */
1796 Status = CmpQueryKeyData(Hive,
1797 Child,
1799 KeyInformation,
1800 Length,
1801 ResultLength);
1802 }
1804 {
1805 /* Fail with exception code */
1807 _SEH2_YIELD(goto Quickie);
1808 }
1809 _SEH2_END;
1810
1811Quickie:
1812 /* Release references */
1813 HvReleaseFreeCellRefArray(&CellReferences);
1814
1815 /* Release locks */
1816 CmpReleaseKcbLock(Kcb);
1818 return Status;
1819}
#define CmpAcquireKcbLockShared(k)
Definition: cm_x.h:145
NTSTATUS NTAPI CmpQueryKeyData(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN KEY_INFORMATION_CLASS KeyInformationClass, IN OUT PVOID KeyInformation, IN ULONG Length, IN OUT PULONG ResultLength)
Definition: cmapi.c:375
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
BOOLEAN CMAPI HvTrackCellRef(IN OUT PHV_TRACK_CELL_REF CellRef, IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:554
VOID CMAPI HvReleaseFreeCellRefArray(IN OUT PHV_TRACK_CELL_REF CellRef)
Definition: hivecell.c:634
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_In_ ULONG _In_ KEY_INFORMATION_CLASS KeyInformationClass
Definition: zwfuncs.h:167

Referenced by NtEnumerateKey().

◆ CmEnumerateValueKey()

NTSTATUS NTAPI CmEnumerateValueKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN ULONG  Index,
IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
IN PVOID  KeyValueInformation,
IN ULONG  Length,
IN PULONG  ResultLength 
)

Definition at line 1191 of file cmapi.c.

1197{
1199 PHHIVE Hive;
1201 HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL;
1203 BOOLEAN IndexIsCached, ValueIsCached = FALSE;
1204 PCELL_DATA CellData;
1205 PCM_CACHED_VALUE *CachedValue;
1207 PAGED_CODE();
1208
1209 /* Acquire hive lock */
1211
1212 /* Lock the KCB shared */
1214
1215 /* Don't touch deleted keys */
1216DoAgain:
1217 if (Kcb->Delete)
1218 {
1219 /* Undo everything */
1220 CmpReleaseKcbLock(Kcb);
1222 return STATUS_KEY_DELETED;
1223 }
1224
1225 /* Get the hive and parent */
1226 Hive = Kcb->KeyHive;
1227 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1228 ASSERT(Parent);
1229
1230 /* FIXME: Lack of cache? */
1231 if (Kcb->ValueCache.Count != Parent->ValueList.Count)
1232 {
1233 DPRINT1("HACK: Overriding value cache count\n");
1234 Kcb->ValueCache.Count = Parent->ValueList.Count;
1235 }
1236
1237 /* Make sure the index is valid */
1238 if (Index >= Kcb->ValueCache.Count)
1239 {
1240 /* Release the cell and fail */
1241 HvReleaseCell(Hive, Kcb->KeyCell);
1243 goto Quickie;
1244 }
1245
1246 /* We don't deal with this yet */
1247 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1248 {
1249 /* Shouldn't happen */
1250 ASSERT(FALSE);
1251 }
1252
1253 /* Find the value list */
1255 &CellData,
1256 &IndexIsCached,
1257 &CellToRelease);
1259 {
1260 /* Check if we need an exclusive lock */
1261 ASSERT(CellToRelease == HCELL_NIL);
1262 HvReleaseCell(Hive, Kcb->KeyCell);
1263
1264 /* Try with exclusive KCB lock */
1266 goto DoAgain;
1267 }
1268 else if (Result != SearchSuccess)
1269 {
1270 /* Sanity check */
1271 ASSERT(CellData == NULL);
1272
1273 /* Release the cell and fail */
1275 goto Quickie;
1276 }
1277
1278 /* Now get the key value */
1280 CellData,
1281 Index,
1282 &CachedValue,
1283 &ValueData,
1284 IndexIsCached,
1285 &ValueIsCached,
1286 &CellToRelease2);
1288 {
1289 /* Cleanup state */
1290 ASSERT(CellToRelease2 == HCELL_NIL);
1291 if (CellToRelease)
1292 {
1293 HvReleaseCell(Hive, CellToRelease);
1294 CellToRelease = HCELL_NIL;
1295 }
1296 HvReleaseCell(Hive, Kcb->KeyCell);
1297
1298 /* Try with exclusive KCB lock */
1300 goto DoAgain;
1301 }
1302 else if (Result != SearchSuccess)
1303 {
1304 /* Sanity check */
1305 ASSERT(ValueData == NULL);
1306
1307 /* Release the cells and fail */
1309 goto Quickie;
1310 }
1311
1312 /* User data, need SEH */
1313 _SEH2_TRY
1314 {
1315 /* Query the information requested */
1317 CachedValue,
1318 ValueData,
1319 ValueIsCached,
1321 KeyValueInformation,
1322 Length,
1324 &Status);
1326 {
1327 /* Cleanup state */
1328 if (CellToRelease2) HvReleaseCell(Hive, CellToRelease2);
1329 HvReleaseCell(Hive, Kcb->KeyCell);
1330 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
1331
1332 /* Try with exclusive KCB lock */
1334 _SEH2_YIELD(goto DoAgain);
1335 }
1336 }
1338 {
1339 /* Get exception code */
1341 }
1342 _SEH2_END;
1343
1344Quickie:
1345 /* If we have a cell to release, do so */
1346 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1347
1348 /* Release the parent cell */
1349 HvReleaseCell(Hive, Kcb->KeyCell);
1350
1351 /* If we have a cell to release, do so */
1352 if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
1353
1354 /* Release locks */
1355 CmpReleaseKcbLock(Kcb);
1357 return Status;
1358}
#define PAGED_CODE()
#define DPRINT1
Definition: precomp.h:8
enum _VALUE_SEARCH_RETURN_TYPE VALUE_SEARCH_RETURN_TYPE
@ SearchSuccess
Definition: cm.h:139
@ SearchNeedExclusiveLock
Definition: cm.h:140
FORCEINLINE VOID CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:205
VALUE_SEARCH_RETURN_TYPE NTAPI CmpQueryKeyValueData(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PCM_CACHED_VALUE *CachedValue, IN PCM_KEY_VALUE ValueKey, IN BOOLEAN ValueIsCached, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength, OUT PNTSTATUS Status)
Definition: cmvalche.c:327
VALUE_SEARCH_RETURN_TYPE NTAPI CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb, OUT PCELL_DATA *CellData, OUT BOOLEAN *IndexIsCached, OUT PHCELL_INDEX ValueListToRelease)
Definition: cmvalche.c:44
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)
Definition: cmvalche.c:96
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
_In_ ULONG _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
Definition: cmfuncs.h:94

Referenced by NtEnumerateValueKey().

◆ CmFlushKey()

NTSTATUS NTAPI CmFlushKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN BOOLEAN  ExclusiveLock 
)

Definition at line 1937 of file cmapi.c.

1939{
1940 PCMHIVE CmHive;
1941#if DBG
1942 CM_CHECK_REGISTRY_STATUS CheckStatus;
1943#endif
1945 PHHIVE Hive;
1946
1947 /* Ignore flushes until we're ready */
1948 if (CmpNoWrite) return STATUS_SUCCESS;
1949
1950 /* Get the hives */
1951 Hive = Kcb->KeyHive;
1952 CmHive = (PCMHIVE)Hive;
1953
1954 /* Check if this is the master hive */
1955 if (CmHive == CmiVolatileHive)
1956 {
1957 /* Flush all the hives instead */
1959 }
1960 else
1961 {
1962#if DBG
1963 /* Make sure the registry hive we're going to flush is OK */
1965 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
1966#endif
1967
1968 /* Don't touch the hive */
1970
1971 ASSERT(CmHive->ViewLock);
1974
1975 /* Will the hive shrink? */
1976 if (HvHiveWillShrink(Hive))
1977 {
1978 /* I don't believe the current Hv does shrinking */
1979 ASSERT(FALSE);
1980 // CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive);
1981 }
1982 else
1983 {
1984 /* Now we can release views */
1985 ASSERT(CmHive->ViewLock);
1986 // CMP_ASSERT_VIEW_LOCK_OWNED(CmHive);
1988 (CmHive->HiveIsLoading == TRUE) ||
1989 (CmHive->ViewLockOwner == KeGetCurrentThread()) ||
1991 CmHive->ViewLockOwner = NULL;
1993 }
1994
1995 /* Flush only this hive */
1996 if (!HvSyncHive(Hive))
1997 {
1998 /* Fail */
2000 }
2001
2002 /* Release the flush lock */
2003 CmpUnlockHiveFlusher(CmHive);
2004 }
2005
2006 /* Return the status */
2007 return Status;
2008}
BOOLEAN NTAPI CmpDoFlushAll(IN BOOLEAN ForceFlush)
Definition: cmapi.c:81
CM_CHECK_REGISTRY_STATUS NTAPI CmCheckRegistry(_In_ PCMHIVE RegistryHive, _In_ ULONG Flags)
Checks the registry that is consistent and its contents valid and not corrupted. More specifically th...
Definition: cmcheck.c:1633
#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES
Definition: cmlib.h:228
BOOLEAN CMAPI HvHiveWillShrink(IN PHHIVE RegistryHive)
BOOLEAN CMAPI HvSyncHive(PHHIVE RegistryHive)
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
Definition: cmlib.h:231
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
struct _CMHIVE * PCMHIVE
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
VOID NTAPI CmpLockHiveFlusherExclusive(IN PCMHIVE Hive)
Definition: cmsysini.c:2006
BOOLEAN CmpSpecialBootCondition
Definition: cmsysini.c:26
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
BOOLEAN NTAPI CmpTestRegistryLockExclusive(VOID)
Definition: cmsysini.c:1998
BOOLEAN CmpNoWrite
Definition: cmsysini.c:30
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define KeGetCurrentThread
Definition: hal.h:55
#define STATUS_REGISTRY_IO_FAILED
Definition: ntstatus.h:569
BOOLEAN HiveIsLoading
Definition: cmlib.h:357
PKGUARDED_MUTEX ViewLock
Definition: cmlib.h:323
PKTHREAD ViewLockOwner
Definition: cmlib.h:324

Referenced by CmUnloadKey(), and NtFlushKey().

◆ CmLoadKey()

NTSTATUS NTAPI CmLoadKey ( IN POBJECT_ATTRIBUTES  TargetKey,
IN POBJECT_ATTRIBUTES  SourceFile,
IN ULONG  Flags,
IN PCM_KEY_BODY  KeyBody 
)

Definition at line 2012 of file cmapi.c.

2016{
2017 SECURITY_QUALITY_OF_SERVICE ServiceQos;
2018 SECURITY_CLIENT_CONTEXT ClientSecurityContext;
2021 PCMHIVE CmHive, LoadedHive;
2023 CM_PARSE_CONTEXT ParseContext;
2024
2025 /* Check if we have a trust key */
2026 if (KeyBody)
2027 {
2028 /* Fail */
2029 DPRINT("Trusted classes not yet supported\n");
2030 }
2031
2032 /* Build a service QoS for a security context */
2033 ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2036 ServiceQos.EffectiveOnly = TRUE;
2038 &ServiceQos,
2039 FALSE,
2040 &ClientSecurityContext);
2041 if (!NT_SUCCESS(Status))
2042 {
2043 /* Fail */
2044 DPRINT1("Security context failed\n");
2045 return Status;
2046 }
2047
2048 /* Open the target key */
2049 RtlZeroMemory(&ParseContext, sizeof(ParseContext));
2050 ParseContext.CreateOperation = FALSE;
2051 Status = ObOpenObjectByName(TargetKey,
2053 KernelMode,
2054 NULL,
2055 KEY_READ,
2056 &ParseContext,
2057 &KeyHandle);
2059
2060 /* Open the hive */
2061 Status = CmpCmdHiveOpen(SourceFile,
2062 &ClientSecurityContext,
2063 &Allocate,
2064 &CmHive,
2066
2067 /* Get rid of the security context */
2068 SeDeleteClientSecurity(&ClientSecurityContext);
2069
2070 /* See if we failed */
2071 if (!NT_SUCCESS(Status))
2072 {
2073 /* See if the target already existed */
2074 if (KeyHandle)
2075 {
2076 /* Lock the registry */
2078
2079 /* Check if we are already loaded */
2080 if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive))
2081 {
2082 /* That's okay then */
2083 ASSERT(LoadedHive);
2085 }
2086
2087 /* Release the registry */
2089 }
2090
2091 /* Close the key handle if we had one */
2093 return Status;
2094 }
2095
2096 /* Lock the registry shared */
2098
2099 /* Lock loading */
2101
2102 /* Lock the hive to this thread */
2103 CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
2104 CmHive->CreatorOwner = KeGetCurrentThread();
2105
2106 /* Set flag */
2108
2109 /* Link the hive */
2110 Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
2111 TargetKey->RootDirectory,
2112 CmHive,
2113 Allocate,
2114 TargetKey->SecurityDescriptor);
2115 if (NT_SUCCESS(Status))
2116 {
2117 /* Add to HiveList key */
2118 CmpAddToHiveFileList(CmHive);
2119
2120 /* Sync the hive if necessary */
2121 if (Allocate)
2122 {
2123 /* Sync it under the flusher lock */
2125 HvSyncHive(&CmHive->Hive);
2126 CmpUnlockHiveFlusher(CmHive);
2127 }
2128
2129 /* Release the hive */
2130 CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
2131 CmHive->CreatorOwner = NULL;
2132 }
2133 else
2134 {
2135 DPRINT1("CmpLinkHiveToMaster failed, Status %lx\n", Status);
2136
2137 /* We're touching this hive, set the loading flag */
2138 CmHive->HiveIsLoading = TRUE;
2139
2140 /* Close associated file handles */
2141 CmpCloseHiveFiles(CmHive);
2142
2143 /* Cleanup its resources */
2144 CmpDestroyHive(CmHive);
2145 }
2146
2147 /* Allow loads */
2149
2150 /* Is this first profile load? */
2152 {
2153 /* User is now logged on, set quotas */
2156 }
2157
2158 /* Unlock the registry */
2160
2161 /* Close handle and return */
2163 return Status;
2164}
#define CmpKeyObjectType
Definition: ObTypes.c:127
BOOLEAN NTAPI CmpIsHiveAlreadyLoaded(IN HANDLE KeyHandle, IN POBJECT_ATTRIBUTES SourceFile, OUT PCMHIVE *CmHive)
Definition: cmapi.c:21
EX_PUSH_LOCK CmpLoadHiveLock
Definition: cmdata.c:39
NTSTATUS NTAPI CmpAddToHiveFileList(IN PCMHIVE Hive)
Definition: cmhvlist.c:130
NTSTATUS NTAPI CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes, IN PSECURITY_CLIENT_CONTEXT ImpersonationContext, IN OUT PBOOLEAN Allocate, OUT PCMHIVE *NewHive, IN ULONG CheckFlags)
Definition: cmlazy.c:276
#define CM_CHECK_REGISTRY_PURGE_VOLATILES
Definition: cmlib.h:229
VOID NTAPI CmpSetGlobalQuotaAllowed(VOID)
Definition: cmquota.c:22
VOID NTAPI CmpLockRegistryExclusive(VOID)
Definition: cmsysini.c:1957
NTSTATUS NTAPI CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, IN HANDLE RootDirectory, IN PCMHIVE RegistryHive, IN BOOLEAN Allocate, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: cmsysini.c:802
BOOLEAN CmpProfileLoaded
Definition: cmsysini.c:33
BOOLEAN CmpWasSetupBoot
Definition: cmsysini.c:32
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
FORCEINLINE VOID ExReleasePushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1296
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
#define HIVE_IS_UNLOADING
Definition: hivedata.h:28
#define HIVE_NOLAZYFLUSH
Definition: hivedata.h:24
@ SecurityImpersonation
Definition: lsa.idl:57
struct _SECURITY_QUALITY_OF_SERVICE SECURITY_QUALITY_OF_SERVICE
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
NTKERNELAPI NTSTATUS NTAPI SeCreateClientSecurity(IN PETHREAD Thread, IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, IN BOOLEAN RemoteClient, OUT PSECURITY_CLIENT_CONTEXT ClientContext)
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define REG_NO_LAZY_FLUSH
Definition: nt_native.h:1093
#define KEY_READ
Definition: nt_native.h:1023
VOID NTAPI CmpCloseHiveFiles(IN PCMHIVE Hive)
Definition: cminit.c:644
NTSTATUS NTAPI CmpDestroyHive(IN PCMHIVE CmHive)
Definition: cminit.c:242
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2532
#define DPRINT
Definition: sndvol32.h:73
HHIVE Hive
Definition: cmlib.h:317
PKTHREAD CreatorOwner
Definition: cmlib.h:358
BOOLEAN CreateOperation
Definition: cm.h:441
ULONG HiveFlags
Definition: hivedata.h:347
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PALLOCATE_FUNCTION Allocate
Definition: exfuncs.h:814
#define SECURITY_DYNAMIC_TRACKING
Definition: setypes.h:103

Referenced by NtLoadKeyEx().

◆ CmpDeepCopyKey()

NTSTATUS NTAPI CmpDeepCopyKey ( IN PHHIVE  SourceHive,
IN HCELL_INDEX  SrcKeyCell,
IN PHHIVE  DestinationHive,
IN HSTORAGE_TYPE  StorageType,
OUT PHCELL_INDEX DestKeyCell  OPTIONAL 
)

Definition at line 2644 of file cmapi.c.

2649{
2650 /* Call the internal function */
2651 return CmpDeepCopyKeyInternal(SourceHive,
2652 SrcKeyCell,
2653 DestinationHive,
2654 HCELL_NIL,
2655 StorageType,
2656 DestKeyCell);
2657}
static NTSTATUS CmpDeepCopyKeyInternal(IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HCELL_INDEX Parent, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
Definition: cmapi.c:2468

Referenced by CmSaveKey(), and CmSaveMergedKeys().

◆ CmpDeepCopyKeyInternal()

static NTSTATUS CmpDeepCopyKeyInternal ( IN PHHIVE  SourceHive,
IN HCELL_INDEX  SrcKeyCell,
IN PHHIVE  DestinationHive,
IN HCELL_INDEX  Parent,
IN HSTORAGE_TYPE  StorageType,
OUT PHCELL_INDEX DestKeyCell  OPTIONAL 
)
static

Definition at line 2468 of file cmapi.c.

2474{
2476 PCM_KEY_NODE SrcNode;
2477 PCM_KEY_NODE DestNode = NULL;
2478 HCELL_INDEX NewKeyCell = HCELL_NIL;
2479 HCELL_INDEX NewClassCell = HCELL_NIL, NewSecCell = HCELL_NIL;
2480 HCELL_INDEX SubKey, NewSubKey;
2481 ULONG Index, SubKeyCount;
2482
2483 PAGED_CODE();
2484
2485 DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
2486 SourceHive,
2487 SrcKeyCell,
2488 DestinationHive,
2489 Parent,
2490 StorageType,
2491 DestKeyCell);
2492
2493 /* Get the source cell node */
2494 SrcNode = (PCM_KEY_NODE)HvGetCell(SourceHive, SrcKeyCell);
2495 ASSERT(SrcNode);
2496
2497 /* Sanity check */
2499
2500 /* Create a simple copy of the source key */
2501 NewKeyCell = CmpCopyCell(SourceHive,
2502 SrcKeyCell,
2503 DestinationHive,
2504 StorageType);
2505 if (NewKeyCell == HCELL_NIL)
2506 {
2507 /* Not enough storage space */
2509 goto Cleanup;
2510 }
2511
2512 /* Get the destination cell node */
2513 DestNode = (PCM_KEY_NODE)HvGetCell(DestinationHive, NewKeyCell);
2514 ASSERT(DestNode);
2515
2516 /* Set the parent and copy the flags */
2517 DestNode->Parent = Parent;
2518 DestNode->Flags = (SrcNode->Flags & KEY_COMP_NAME); // Keep only the single permanent flag
2519 if (Parent == HCELL_NIL)
2520 {
2521 /* This is the new root node */
2522 DestNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
2523 }
2524
2525 /* Copy the class cell */
2526 if (SrcNode->ClassLength > 0)
2527 {
2528 NewClassCell = CmpCopyCell(SourceHive,
2529 SrcNode->Class,
2530 DestinationHive,
2531 StorageType);
2532 if (NewClassCell == HCELL_NIL)
2533 {
2534 /* Not enough storage space */
2536 goto Cleanup;
2537 }
2538
2539 DestNode->Class = NewClassCell;
2540 DestNode->ClassLength = SrcNode->ClassLength;
2541 }
2542 else
2543 {
2544 DestNode->Class = HCELL_NIL;
2545 DestNode->ClassLength = 0;
2546 }
2547
2548 /* Copy the security cell (FIXME: HACKish poor-man version) */
2549 if (SrcNode->Security != HCELL_NIL)
2550 {
2551 NewSecCell = CmpCopyCell(SourceHive,
2552 SrcNode->Security,
2553 DestinationHive,
2554 StorageType);
2555 if (NewSecCell == HCELL_NIL)
2556 {
2557 /* Not enough storage space */
2559 goto Cleanup;
2560 }
2561 }
2562 DestNode->Security = NewSecCell;
2563
2564 /* Copy the value list */
2565 Status = CmpCopyKeyValueList(SourceHive,
2566 &SrcNode->ValueList,
2567 DestinationHive,
2568 &DestNode->ValueList,
2569 StorageType);
2570 if (!NT_SUCCESS(Status))
2571 goto Cleanup;
2572
2573 /* Clear the invalid subkey index */
2574 DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
2575 DestNode->SubKeyLists[Stable] = DestNode->SubKeyLists[Volatile] = HCELL_NIL;
2576
2577 /* Calculate the total number of subkeys */
2578 SubKeyCount = SrcNode->SubKeyCounts[Stable] + SrcNode->SubKeyCounts[Volatile];
2579
2580 /* Loop through all the subkeys */
2581 for (Index = 0; Index < SubKeyCount; Index++)
2582 {
2583 /* Get the subkey */
2584 SubKey = CmpFindSubKeyByNumber(SourceHive, SrcNode, Index);
2585 ASSERT(SubKey != HCELL_NIL);
2586
2587 /* Call the function recursively for the subkey */
2588 //
2589 // FIXME: Danger!! Kernel stack exhaustion!!
2590 //
2591 Status = CmpDeepCopyKeyInternal(SourceHive,
2592 SubKey,
2593 DestinationHive,
2594 NewKeyCell,
2595 StorageType,
2596 &NewSubKey);
2597 if (!NT_SUCCESS(Status))
2598 goto Cleanup;
2599
2600 /* Add the copy of the subkey to the new key */
2601 if (!CmpAddSubKey(DestinationHive,
2602 NewKeyCell,
2603 NewSubKey))
2604 {
2605 /* Cleanup allocated cell */
2606 HvFreeCell(DestinationHive, NewSubKey);
2607
2609 goto Cleanup;
2610 }
2611 }
2612
2613 /* Set success */
2615
2616Cleanup:
2617
2618 /* Release the cells */
2619 if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
2620 if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
2621
2622 /* Cleanup allocated cells in case of failure */
2623 if (!NT_SUCCESS(Status))
2624 {
2625 if (NewSecCell != HCELL_NIL)
2626 HvFreeCell(DestinationHive, NewSecCell);
2627
2628 if (NewClassCell != HCELL_NIL)
2629 HvFreeCell(DestinationHive, NewClassCell);
2630
2631 if (NewKeyCell != HCELL_NIL)
2632 HvFreeCell(DestinationHive, NewKeyCell);
2633
2634 NewKeyCell = HCELL_NIL;
2635 }
2636
2637 /* Set the cell index if requested and return status */
2638 if (DestKeyCell) *DestKeyCell = NewKeyCell;
2639 return Status;
2640}
HCELL_INDEX NTAPI CmpCopyCell(IN PHHIVE SourceHive, IN HCELL_INDEX SourceCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType)
Definition: cmvalue.c:376
#define KEY_COMP_NAME
Definition: cmdata.h:35
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
BOOLEAN NTAPI CmpAddSubKey(IN PHHIVE Hive, IN HCELL_INDEX Parent, IN HCELL_INDEX Child)
Definition: cmindex.c:1465
NTSTATUS NTAPI CmpCopyKeyValueList(IN PHHIVE SourceHive, IN PCHILD_LIST SrcValueList, IN PHHIVE DestinationHive, IN OUT PCHILD_LIST DestValueList, IN HSTORAGE_TYPE StorageType)
Definition: cmvalue.c:521
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:468
static const WCHAR Cleanup[]
Definition: register.c:80
USHORT Signature
Definition: cmdata.h:92
HCELL_INDEX Parent
Definition: cmdata.h:96
HCELL_INDEX SubKeyLists[HTYPE_COUNT]
Definition: cmdata.h:102
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97
HCELL_INDEX Security
Definition: cmdata.h:107
USHORT ClassLength
Definition: cmdata.h:115
HCELL_INDEX Class
Definition: cmdata.h:108
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93

Referenced by CmpDeepCopyKey(), and CmpDeepCopyKeyInternal().

◆ CmpDoFlushAll()

BOOLEAN NTAPI CmpDoFlushAll ( IN BOOLEAN  ForceFlush)

Definition at line 81 of file cmapi.c.

82{
83 PLIST_ENTRY NextEntry;
84 PCMHIVE Hive;
87
88 /* Make sure that the registry isn't read-only now */
89 if (CmpNoWrite) return TRUE;
90
91 /* Otherwise, acquire the hive list lock and disable force flush */
94
95 /* Loop the hive list */
96 NextEntry = CmpHiveListHead.Flink;
97 while (NextEntry != &CmpHiveListHead)
98 {
99 /* Get the hive */
100 Hive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList);
101 if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
102 {
103 /* Acquire the flusher lock */
105
106 /* Check for illegal state */
107 if (ForceFlush && Hive->UseCount)
108 {
109 /* Registry needs to be locked down */
111 UNIMPLEMENTED_DBGBREAK("FIXME: Hive is damaged and needs fixup\n");
112 }
113
114 /* Only sync if we are forced to or if it won't cause a hive shrink */
115 if (ForceFlush || !HvHiveWillShrink(&Hive->Hive))
116 {
117 /* Do the sync */
118 Status = HvSyncHive(&Hive->Hive);
119
120 /* If something failed - set the flag and continue looping */
121 if (!NT_SUCCESS(Status))
122 Result = FALSE;
123 }
124 else
125 {
126 /* We won't flush if the hive might shrink */
127 Result = FALSE;
129 }
130
131 /* Release the flusher lock */
133 }
134
135 /* Try the next entry */
136 NextEntry = NextEntry->Flink;
137 }
138
139 /* Release lock and return */
141 return Result;
142}
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK()
Definition: cm_x.h:67
EX_PUSH_LOCK CmpHiveListHeadLock
Definition: cmdata.c:39
BOOLEAN CmpForceForceFlush
Definition: cmlazy.c:22
LIST_ENTRY CmpHiveListHead
Definition: cmsysini.c:17
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105
ULONG UseCount
Definition: cmlib.h:337
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by CmFlushKey(), CmpUnlockRegistry(), and CmShutdownSystem().

◆ CmpEnumerateOpenSubKeys()

ULONG NTAPI CmpEnumerateOpenSubKeys ( _In_ PCM_KEY_CONTROL_BLOCK  RootKcb,
_In_ BOOLEAN  LockHeldExclusively,
_In_ BOOLEAN  RemoveEmptyCacheEntries,
_In_ BOOLEAN  DereferenceOpenedEntries 
)

Definition at line 2341 of file cmapi.c.

2346{
2348 PCM_KEY_CONTROL_BLOCK CachedKcb;
2349 PCM_KEY_CONTROL_BLOCK ParentKcb;
2350 ULONG ParentKeyCount;
2351 ULONG i, j;
2352 ULONG SubKeys = 0;
2353
2354 DPRINT("CmpEnumerateOpenSubKeys() called\n");
2355
2356 /* The root key is the only referenced key. There are no referenced sub keys. */
2357 if (RootKcb->RefCount == 1)
2358 {
2359 DPRINT("Open sub keys: 0\n");
2360 return 0;
2361 }
2362
2363 /* Enumerate all hash lists */
2364 for (i = 0; i < CmpHashTableSize; i++)
2365 {
2366 /* Get the first cache entry */
2368
2369 /* Enumerate all cache entries */
2370 while (Entry)
2371 {
2372 /* Get the KCB of the current cache entry */
2374
2375 /* Check keys only that are subkeys to our root key */
2376 if (CachedKcb->TotalLevels > RootKcb->TotalLevels)
2377 {
2378 /* Calculate the number of parent keys to the root key */
2379 ParentKeyCount = CachedKcb->TotalLevels - RootKcb->TotalLevels;
2380
2381 /* Find a parent key that could be the root key */
2382 ParentKcb = CachedKcb;
2383 for (j = 0; j < ParentKeyCount; j++)
2384 {
2385 ParentKcb = ParentKcb->ParentKcb;
2386 }
2387
2388 /* Check whether the parent is the root key */
2389 if (ParentKcb == RootKcb)
2390 {
2391 DPRINT("Found a sub key, RefCount = %u\n", CachedKcb->RefCount);
2392
2393 if (CachedKcb->RefCount > 0)
2394 {
2395 DPRINT("Found a sub key pointing to '%.*s', RefCount = %u\n",
2396 CachedKcb->NameBlock->NameLength, CachedKcb->NameBlock->Name,
2397 CachedKcb->RefCount);
2398
2399 /* If we dereference opened KCBs, don't touch read-only keys */
2400 if (DereferenceOpenedEntries &&
2401 !(CachedKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
2402 {
2403 /* Registry needs to be locked down */
2405
2406 /* Flush any notifications */
2407 CmpFlushNotifiesOnKeyBodyList(CachedKcb, TRUE); // Lock is already held
2408
2409 /* Clean up information we have on the subkey */
2410 CmpCleanUpSubKeyInfo(CachedKcb->ParentKcb);
2411
2412 /* Get and cache the next cache entry */
2413 // Entry = Entry->NextHash;
2414 Entry = CachedKcb->NextHash;
2415
2416 /* Set the KCB in delete mode and remove it */
2417 CachedKcb->Delete = TRUE;
2418 CmpRemoveKeyControlBlock(CachedKcb);
2419
2420 /* Clear the cell */
2421 CachedKcb->KeyCell = HCELL_NIL;
2422
2423 /* Restart with the next cache entry */
2424 continue;
2425 }
2426 /* Else, the key cannot be dereferenced, and we count it as in use */
2427
2428 /* Count the current hash entry if it is in use */
2429 SubKeys++;
2430 }
2431 else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
2432 {
2433 /* Lock the cached KCB of subkey before removing it from cache entries */
2434 if (!LockHeldExclusively)
2435 CmpAcquireKcbLockExclusive(CachedKcb);
2436
2437 /* Remove the current key from the delayed close list */
2438 CmpRemoveFromDelayedClose(CachedKcb);
2439
2440 /* Remove the current cache entry */
2441 // Lock is either held by ourselves or registry is locked exclusively
2442 CmpCleanUpKcbCacheWithLock(CachedKcb, LockHeldExclusively);
2443
2444 /* Unlock the cached KCB if it was done by ourselves */
2445 if (!LockHeldExclusively)
2446 CmpReleaseKcbLock(CachedKcb);
2447
2448 /* Restart, because the hash list has changed */
2450 continue;
2451 }
2452 }
2453 }
2454
2455 /* Get the next cache entry */
2456 Entry = Entry->NextHash;
2457 }
2458 }
2459
2460 if (SubKeys > 0)
2461 DPRINT1("Open sub keys: %u\n", SubKeys);
2462
2463 return SubKeys;
2464}
#define CM_KCB_READ_ONLY_KEY
Definition: cm.h:59
VOID NTAPI CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:425
VOID NTAPI CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:476
PCM_KEY_HASH_TABLE_ENTRY CmpCacheTable
Definition: cmkcbncb.c:18
ULONG CmpHashTableSize
Definition: cmkcbncb.c:17
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
base of all file and directory entries
Definition: entries.h:83
ULONG TotalLevels
Definition: cm.h:276
PCM_NAME_CONTROL_BLOCK NameBlock
Definition: cm.h:290
ULONG RefCount
Definition: cm.h:269
ULONG ExtFlags
Definition: cm.h:272
PCM_KEY_HASH NextHash
Definition: cm.h:284
PCM_KEY_HASH Entry
Definition: cm.h:162
USHORT NameLength
Definition: cm.h:257
WCHAR Name[ANYSIZE_ARRAY]
Definition: cm.h:258

Referenced by CmUnloadKey(), and NtQueryOpenSubKeys().

◆ CmpIsHiveAlreadyLoaded()

BOOLEAN NTAPI CmpIsHiveAlreadyLoaded ( IN HANDLE  KeyHandle,
IN POBJECT_ATTRIBUTES  SourceFile,
OUT PCMHIVE CmHive 
)

Definition at line 21 of file cmapi.c.

24{
26 PCM_KEY_BODY KeyBody;
27 PCMHIVE Hive;
29 PAGED_CODE();
30
31 /* Sanity check */
33
34 /* Reference the handle */
36 0,
39 (PVOID)&KeyBody,
40 NULL);
41 if (!NT_SUCCESS(Status)) return Loaded;
42
43 /* Don't touch deleted KCBs */
44 if (KeyBody->KeyControlBlock->Delete) return Loaded;
45
46 Hive = CONTAINING_RECORD(KeyBody->KeyControlBlock->KeyHive, CMHIVE, Hive);
47
48 /* Must be the root key */
49 if (!(KeyBody->KeyControlBlock->Flags & KEY_HIVE_ENTRY) ||
50 !(Hive->FileUserName.Buffer))
51 {
52 /* It isn't */
53 ObDereferenceObject(KeyBody);
54 return Loaded;
55 }
56
57 /* Now compare the name of the file */
59 SourceFile->ObjectName,
60 TRUE))
61 {
62 /* Same file found */
63 Loaded = TRUE;
64 *CmHive = Hive;
65
66 /* If the hive is frozen, not sure what to do */
67 if (Hive->Frozen)
68 {
69 /* FIXME: TODO */
70 UNIMPLEMENTED_DBGBREAK("ERROR: Hive is frozen\n");
71 }
72 }
73
74 /* Dereference and return result */
75 ObDereferenceObject(KeyBody);
76 return Loaded;
77 }
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
@ Loaded
Definition: fs_rec.h:187
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
BOOLEAN Frozen
Definition: cmlib.h:345
UNICODE_STRING FileUserName
Definition: cmlib.h:334
struct _CM_KEY_CONTROL_BLOCK * KeyControlBlock
Definition: cm.h:234
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by CmLoadKey().

◆ CmpQueryFlagsInformation()

static NTSTATUS CmpQueryFlagsInformation ( _In_ PCM_KEY_CONTROL_BLOCK  Kcb,
_Out_ PKEY_USER_FLAGS_INFORMATION  KeyFlagsInfo,
_In_ ULONG  Length,
_In_ PULONG  ResultLength 
)
static

Definition at line 1497 of file cmapi.c.

1502{
1503 /* Validate the buffer size */
1504 *ResultLength = sizeof(*KeyFlagsInfo);
1505 if (Length < *ResultLength)
1506 {
1508 }
1509
1510 /* Copy the user flags */
1511 KeyFlagsInfo->UserFlags = Kcb->KcbUserFlags;
1512
1513 return STATUS_SUCCESS;
1514}
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69

Referenced by CmQueryKey().

◆ CmpQueryKeyData()

NTSTATUS NTAPI CmpQueryKeyData ( IN PHHIVE  Hive,
IN PCM_KEY_NODE  Node,
IN KEY_INFORMATION_CLASS  KeyInformationClass,
IN OUT PVOID  KeyInformation,
IN ULONG  Length,
IN OUT PULONG  ResultLength 
)

Definition at line 375 of file cmapi.c.

381{
383 ULONG Size, SizeLeft, MinimumSize, Offset;
384 PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
385 USHORT NameLength;
387
388 /* Check if the value is compressed */
389 if (Node->Flags & KEY_COMP_NAME)
390 {
391 /* Get the compressed name size */
392 NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
393 }
394 else
395 {
396 /* Get the real size */
397 NameLength = Node->NameLength;
398 }
399
400 /* Check what kind of information is being requested */
401 switch (KeyInformationClass)
402 {
403 /* Basic information */
405
406 /* This is the size we need */
408
409 /* And this is the minimum we can work with */
411
412 /* Let the caller know and assume success */
415
416 /* Check if the bufer we got is too small */
417 if (Length < MinimumSize)
418 {
419 /* Let the caller know and fail */
421 break;
422 }
423
424 /* Copy the basic information */
425 Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
426 Info->KeyBasicInformation.TitleIndex = 0;
427 Info->KeyBasicInformation.NameLength = NameLength;
428
429 /* Only the name is left */
430 SizeLeft = Length - MinimumSize;
431 Size = NameLength;
432
433 /* Check if we don't have enough space for the name */
434 if (SizeLeft < Size)
435 {
436 /* Truncate the name we'll return, and tell the caller */
437 Size = SizeLeft;
439 }
440
441 /* Check if this is a compressed key */
442 if (Node->Flags & KEY_COMP_NAME)
443 {
444 /* Copy the compressed name */
445 CmpCopyCompressedName(Info->KeyBasicInformation.Name,
446 SizeLeft,
447 Node->Name,
448 Node->NameLength);
449 }
450 else
451 {
452 /* Otherwise, copy the raw name */
453 RtlCopyMemory(Info->KeyBasicInformation.Name,
454 Node->Name,
455 Size);
456 }
457 break;
458
459 /* Node information */
461
462 /* Calculate the size we need */
464 NameLength +
465 Node->ClassLength;
466
467 /* And the minimum size we can support */
468 MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
469
470 /* Return the size to the caller and assume succes */
473
474 /* Check if the caller's buffer is too small */
475 if (Length < MinimumSize)
476 {
477 /* Let them know, and fail */
479 break;
480 }
481
482 /* Copy the basic information */
483 Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
484 Info->KeyNodeInformation.TitleIndex = 0;
485 Info->KeyNodeInformation.ClassLength = Node->ClassLength;
486 Info->KeyNodeInformation.NameLength = NameLength;
487
488 /* Now the name is left */
489 SizeLeft = Length - MinimumSize;
490 Size = NameLength;
491
492 /* Check if the name can fit entirely */
493 if (SizeLeft < Size)
494 {
495 /* It can't, we'll have to truncate. Tell the caller */
496 Size = SizeLeft;
498 }
499
500 /* Check if the key node name is compressed */
501 if (Node->Flags & KEY_COMP_NAME)
502 {
503 /* Copy the compressed name */
504 CmpCopyCompressedName(Info->KeyNodeInformation.Name,
505 SizeLeft,
506 Node->Name,
507 Node->NameLength);
508 }
509 else
510 {
511 /* It isn't, so copy the raw name */
512 RtlCopyMemory(Info->KeyNodeInformation.Name,
513 Node->Name,
514 Size);
515 }
516
517 /* Check if the node has a class */
518 if (Node->ClassLength > 0)
519 {
520 /* Set the class offset */
522 Offset = ALIGN_UP_BY(Offset, sizeof(ULONG));
523 Info->KeyNodeInformation.ClassOffset = Offset;
524
525 /* Get the class data */
526 ClassData = HvGetCell(Hive, Node->Class);
527 if (ClassData == NULL)
528 {
530 break;
531 }
532
533 /* Check if we can copy anything */
534 if (Length > Offset)
535 {
536 /* Copy the class data */
538 ClassData,
539 min(Node->ClassLength, Length - Offset));
540 }
541
542 /* Check if the buffer was large enough */
543 if (Length < Offset + Node->ClassLength)
544 {
546 }
547
548 /* Release the class cell */
549 HvReleaseCell(Hive, Node->Class);
550 }
551 else
552 {
553 /* It doesn't, so set offset to -1, not 0! */
554 Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
555 }
556 break;
557
558 /* Full information requsted */
560
561 /* This is the size we need */
563 Node->ClassLength;
564
565 /* This is what we can work with */
567
568 /* Return it to caller and assume success */
571
572 /* Check if the caller's buffer is to small */
573 if (Length < MinimumSize)
574 {
575 /* Let them know and fail */
577 break;
578 }
579
580 /* Now copy all the basic information */
581 Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
582 Info->KeyFullInformation.TitleIndex = 0;
583 Info->KeyFullInformation.ClassLength = Node->ClassLength;
584 Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
585 Node->SubKeyCounts[Volatile];
586 Info->KeyFullInformation.Values = Node->ValueList.Count;
587 Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
588 Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
589 Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
590 Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
591
592 /* Check if we have a class */
593 if (Node->ClassLength > 0)
594 {
595 /* Set the class offset */
597 Info->KeyFullInformation.ClassOffset = Offset;
598
599 /* Get the class data */
600 ClassData = HvGetCell(Hive, Node->Class);
601 if (ClassData == NULL)
602 {
604 break;
605 }
606
607 /* Copy the class data */
608 ASSERT(Length >= Offset);
609 RtlCopyMemory(Info->KeyFullInformation.Class,
610 ClassData,
611 min(Node->ClassLength, Length - Offset));
612
613 /* Check if the buffer was large enough */
614 if (Length < Offset + Node->ClassLength)
615 {
617 }
618
619 /* Release the class cell */
620 HvReleaseCell(Hive, Node->Class);
621 }
622 else
623 {
624 /* We don't have a class, so set offset to -1, not 0! */
625 Info->KeyFullInformation.ClassOffset = 0xFFFFFFFF;
626 }
627 break;
628
629 /* Any other class that got sent here is invalid! */
630 default:
631
632 /* Set failure code */
634 break;
635 }
636
637 /* Return status */
638 return Status;
639}
#define ALIGN_UP_BY(size, align)
_Out_ PVOID * ClassData
Definition: batclass.h:336
struct _KEY_INFORMATION * PKEY_INFORMATION
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define min(a, b)
Definition: monoChain.cc:55
@ KeyBasicInformation
Definition: nt_native.h:1131
@ KeyNodeInformation
Definition: nt_native.h:1132
@ KeyFullInformation
Definition: nt_native.h:1133
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by CmEnumerateKey(), and CmQueryKey().

◆ CmpQueryKeyDataFromCache()

static NTSTATUS CmpQueryKeyDataFromCache ( _In_ PCM_KEY_CONTROL_BLOCK  Kcb,
_Out_ PKEY_CACHED_INFORMATION  KeyCachedInfo,
_In_ ULONG  Length,
_Out_ PULONG  ResultLength 
)
static

Definition at line 1362 of file cmapi.c.

1367{
1369 PHHIVE KeyHive;
1370 HCELL_INDEX KeyCell;
1371 USHORT NameLength;
1372 PAGED_CODE();
1373
1374 /* Get the hive and cell index */
1375 KeyHive = Kcb->KeyHash.KeyHive;
1376 KeyCell = Kcb->KeyHash.KeyCell;
1377
1378#if DBG
1379 /* Get the cell node */
1380 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1381 if (Node != NULL)
1382 {
1383 ULONG SubKeyCount;
1384 ASSERT(Node->ValueList.Count == Kcb->ValueCache.Count);
1385
1386 if (!(Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO))
1387 {
1388 SubKeyCount = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1389 if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1390 {
1391 ASSERT(SubKeyCount == 0);
1392 }
1393 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1394 {
1395 ASSERT(SubKeyCount == 1);
1396 }
1397 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1398 {
1399 ASSERT(SubKeyCount == Kcb->IndexHint->Count);
1400 }
1401 else
1402 {
1403 ASSERT(SubKeyCount == Kcb->SubKeyCount);
1404 }
1405 }
1406
1407 ASSERT(Node->LastWriteTime.QuadPart == Kcb->KcbLastWriteTime.QuadPart);
1408 ASSERT(Node->MaxNameLen == Kcb->KcbMaxNameLen);
1409 ASSERT(Node->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1410 ASSERT(Node->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1411
1412 /* Release the cell */
1413 HvReleaseCell(KeyHive, KeyCell);
1414 }
1415#endif // DBG
1416
1417 /* Make sure we have a name block */
1418 if (Kcb->NameBlock == NULL)
1419 {
1421 }
1422
1423 /* Check for compressed name */
1424 if (Kcb->NameBlock->Compressed)
1425 {
1426 /* Calculate the name size */
1427 NameLength = CmpCompressedNameSize(Kcb->NameBlock->NameHash.Name,
1428 Kcb->NameBlock->NameHash.NameLength);
1429 }
1430 else
1431 {
1432 /* Use the stored name size */
1433 NameLength = Kcb->NameBlock->NameHash.NameLength;
1434 }
1435
1436 /* Validate buffer length (we do not copy the name!) */
1437 *ResultLength = sizeof(*KeyCachedInfo);
1438 if (Length < *ResultLength)
1439 {
1441 }
1442
1443 /* Fill the structure */
1444 KeyCachedInfo->LastWriteTime = Kcb->KcbLastWriteTime;
1445 KeyCachedInfo->TitleIndex = 0;
1446 KeyCachedInfo->NameLength = NameLength;
1447 KeyCachedInfo->Values = Kcb->ValueCache.Count;
1448 KeyCachedInfo->MaxNameLen = Kcb->KcbMaxNameLen;
1449 KeyCachedInfo->MaxValueNameLen = Kcb->KcbMaxValueNameLen;
1450 KeyCachedInfo->MaxValueDataLen = Kcb->KcbMaxValueDataLen;
1451
1452 /* Check the ExtFlags for what we have */
1453 if (Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO)
1454 {
1455 /* Cache is not valid, do a full lookup */
1456 DPRINT1("Kcb cache incoherency detected, kcb = %p\n", Kcb);
1457
1458 /* Get the cell node */
1459 Node = (PCM_KEY_NODE)HvGetCell(KeyHive, KeyCell);
1460 if (Node == NULL)
1461 {
1463 }
1464
1465 /* Calculate number of subkeys */
1466 KeyCachedInfo->SubKeys = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
1467
1468 /* Release the cell */
1469 HvReleaseCell(KeyHive, KeyCell);
1470 }
1471 else if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
1472 {
1473 /* There are no subkeys */
1474 KeyCachedInfo->SubKeys = 0;
1475 }
1476 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
1477 {
1478 /* There is exactly one subley */
1479 KeyCachedInfo->SubKeys = 1;
1480 }
1481 else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
1482 {
1483 /* Get the number of subkeys from the subkey hint */
1484 KeyCachedInfo->SubKeys = Kcb->IndexHint->Count;
1485 }
1486 else
1487 {
1488 /* No subkey hint, use the key count field */
1489 KeyCachedInfo->SubKeys = Kcb->SubKeyCount;
1490 }
1491
1492 return STATUS_SUCCESS;
1493}
#define CM_KCB_SUBKEY_ONE
Definition: cm.h:53
#define CM_KCB_SUBKEY_HINT
Definition: cm.h:54
#define CM_KCB_INVALID_CACHED_INFO
Definition: cm.h:58
#define CM_KCB_NO_SUBKEY
Definition: cm.h:52

Referenced by CmQueryKey().

◆ CmpQueryNameInformation()

static NTSTATUS CmpQueryNameInformation ( _In_ PCM_KEY_CONTROL_BLOCK  Kcb,
_Out_opt_ PKEY_NAME_INFORMATION  KeyNameInfo,
_In_ ULONG  Length,
_Out_ PULONG  ResultLength 
)
static

Definition at line 1518 of file cmapi.c.

1523{
1524 ULONG NeededLength;
1525 PCM_KEY_CONTROL_BLOCK CurrentKcb;
1526
1527 NeededLength = 0;
1528 CurrentKcb = Kcb;
1529
1530 /* Count the needed buffer size */
1531 while (CurrentKcb)
1532 {
1533 if (CurrentKcb->NameBlock->Compressed)
1534 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1535 else
1536 NeededLength += CurrentKcb->NameBlock->NameLength;
1537
1538 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1539
1540 CurrentKcb = CurrentKcb->ParentKcb;
1541 }
1542
1543 _SEH2_TRY
1544 {
1548 if (Length < *ResultLength)
1549 {
1550 KeyNameInfo->NameLength = NeededLength;
1552 }
1553 }
1555 {
1557 }
1558 _SEH2_END;
1559
1560 /* Do the real copy */
1561 KeyNameInfo->NameLength = 0;
1562 CurrentKcb = Kcb;
1563
1564 _SEH2_TRY
1565 {
1566 while (CurrentKcb)
1567 {
1568 ULONG NameLength;
1569
1570 if (CurrentKcb->NameBlock->Compressed)
1571 {
1572 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1573 /* Copy the compressed name */
1574 CmpCopyCompressedName(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1575 NameLength,
1576 CurrentKcb->NameBlock->Name,
1577 CurrentKcb->NameBlock->NameLength);
1578 }
1579 else
1580 {
1581 NameLength = CurrentKcb->NameBlock->NameLength;
1582 /* Otherwise, copy the raw name */
1583 RtlCopyMemory(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1584 CurrentKcb->NameBlock->Name,
1585 NameLength);
1586 }
1587
1588 NeededLength -= NameLength;
1589 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1590 /* Add path separator */
1591 KeyNameInfo->Name[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1592 KeyNameInfo->NameLength += NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
1593
1594 CurrentKcb = CurrentKcb->ParentKcb;
1595 }
1596 }
1598 {
1600 }
1601 _SEH2_END;
1602
1603 /* Make sure we copied everything */
1604 ASSERT(NeededLength == 0);
1605 ASSERT(KeyNameInfo->Name[0] == OBJ_NAME_PATH_SEPARATOR);
1606
1607 /* We're done */
1608 return STATUS_SUCCESS;
1609}
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
BOOLEAN Compressed
Definition: cm.h:248
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CmQueryKey().

◆ CmpSetValueKeyExisting()

NTSTATUS NTAPI CmpSetValueKeyExisting ( IN PHHIVE  Hive,
IN HCELL_INDEX  OldChild,
IN PCM_KEY_VALUE  Value,
IN ULONG  Type,
IN PVOID  Data,
IN ULONG  DataSize,
IN ULONG  StorageType,
IN ULONG  TempData 
)

Definition at line 270 of file cmapi.c.

278{
279 HCELL_INDEX DataCell, NewCell;
280 PCELL_DATA CellData;
282 BOOLEAN WasSmall, IsSmall;
283
284 /* Registry writes must be blocked */
286
287 /* Mark the old child cell dirty */
288 if (!HvMarkCellDirty(Hive, OldChild, FALSE)) return STATUS_NO_LOG_SPACE;
289
290 /* See if this is a small or normal key */
291 WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength);
292
293 /* See if our new data can fit in a small key */
294 IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
295
296 /* Big keys are unsupported */
299
300 /* Mark the old value dirty */
302
303 /* Check if we have a small key */
304 if (IsSmall)
305 {
306 /* Check if we had a normal key with some data in it */
307 if (!(WasSmall) && (Length > 0))
308 {
309 /* Free the previous data */
310 CmpFreeValueData(Hive, Value->Data, Length);
311 }
312
313 /* Write our data directly */
315 Value->Data = TempData;
316 Value->Type = Type;
317 return STATUS_SUCCESS;
318 }
319
320 /* We have a normal key. Was the old cell also normal and had data? */
321 if (!(WasSmall) && (Length > 0))
322 {
323 /* Get the current data cell and actual data inside it */
324 DataCell = Value->Data;
325 ASSERT(DataCell != HCELL_NIL);
326 CellData = HvGetCell(Hive, DataCell);
327 if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
328
329 /* Immediately release the cell */
330 HvReleaseCell(Hive, DataCell);
331
332 /* Make sure that the data cell actually has a size */
333 ASSERT(HvGetCellSize(Hive, CellData) > 0);
334
335 /* Check if the previous data cell could fit our new data */
336 if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData)))
337 {
338 /* Re-use it then */
339 NewCell = DataCell;
340 }
341 else
342 {
343 /* Otherwise, re-allocate the current data cell */
344 NewCell = HvReallocateCell(Hive, DataCell, DataSize);
345 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
346 }
347 }
348 else
349 {
350 /* This was a small key, or a key with no data, allocate a cell */
351 NewCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
352 if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
353 }
354
355 /* Now get the actual data for our data cell */
356 CellData = HvGetCell(Hive, NewCell);
357 ASSERT(CellData);
358
359 /* Release it immediately */
360 HvReleaseCell(Hive, NewCell);
361
362 /* Copy our data into the data cell's buffer, and set up the value */
363 RtlCopyMemory(CellData, Data, DataSize);
364 Value->Data = NewCell;
365 Value->DataLength = DataSize;
366 Value->Type = Type;
367
368 /* Return success */
369 ASSERT(HvIsCellDirty(Hive, NewCell));
370 return STATUS_SUCCESS;
371}
Type
Definition: Type.h:7
#define CMP_ASSERT_FLUSH_LOCK(h)
Definition: cm_x.h:282
#define CM_KEY_VALUE_SPECIAL_SIZE
Definition: cmdata.h:51
#define CM_KEY_VALUE_SMALL
Definition: cmdata.h:49
BOOLEAN NTAPI CmpFreeValueData(IN PHHIVE Hive, IN HCELL_INDEX DataCell, IN ULONG DataLength)
Definition: cmvalue.c:44
#define ASSERT_VALUE_BIG(h, s)
Definition: cmlib.h:386
static BOOLEAN CmpIsKeyValueSmall(OUT PULONG RealLength, IN ULONG Length)
Definition: cmlib.h:395
LONG CMAPI HvGetCellSize(PHHIVE RegistryHive, PVOID Cell)
HCELL_INDEX CMAPI HvReallocateCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset, ULONG Size)
Definition: hivecell.c:421
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755

Referenced by CmSetValueKey().

◆ CmpSetValueKeyNew()

NTSTATUS NTAPI CmpSetValueKeyNew ( IN PHHIVE  Hive,
IN PCM_KEY_NODE  Parent,
IN PUNICODE_STRING  ValueName,
IN ULONG  Index,
IN ULONG  Type,
IN PVOID  Data,
IN ULONG  DataSize,
IN ULONG  StorageType,
IN ULONG  SmallData 
)

Definition at line 146 of file cmapi.c.

155{
156 PCELL_DATA CellData;
157 HCELL_INDEX ValueCell;
159
160 /* Check if we already have a value list */
161 if (Parent->ValueList.Count)
162 {
163 /* Then make sure it's valid and dirty it */
164 ASSERT(Parent->ValueList.List != HCELL_NIL);
165 if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE))
166 {
167 /* Fail if we're out of space for log changes */
168 return STATUS_NO_LOG_SPACE;
169 }
170 }
171
172 /* Allocate a value cell */
173 ValueCell = HvAllocateCell(Hive,
175 CmpNameSize(Hive, ValueName),
176 StorageType,
177 HCELL_NIL);
178 if (ValueCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
179
180 /* Get the actual data for it */
181 CellData = HvGetCell(Hive, ValueCell);
182 ASSERT(CellData);
183
184 /* Now we can release it, make sure it's also dirty */
185 HvReleaseCell(Hive, ValueCell);
186 ASSERT(HvIsCellDirty(Hive, ValueCell));
187
188 /* Set it up and copy the name */
191 {
192 /* This can crash since the name is coming from user-mode */
193 CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
194 CellData->u.KeyValue.Name,
195 ValueName);
196 }
198 {
199 /* Fail */
200 DPRINT1("Invalid user data!\n");
201 HvFreeCell(Hive, ValueCell);
203 }
204 _SEH2_END;
205
206 /* Check for compressed name */
207 if (CellData->u.KeyValue.NameLength < ValueName->Length)
208 {
209 /* This is a compressed name */
210 CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
211 }
212 else
213 {
214 /* No flags to set */
215 CellData->u.KeyValue.Flags = 0;
216 }
217
218 /* Check if this is a normal key */
220 {
221 /* Build a data cell for it */
223 Data,
224 DataSize,
225 StorageType,
226 ValueCell,
227 &CellData->u.KeyValue.Data);
228 if (!NT_SUCCESS(Status))
229 {
230 /* We failed, free the cell */
231 HvFreeCell(Hive, ValueCell);
232 return Status;
233 }
234
235 /* Otherwise, set the data length, and make sure the data is dirty */
236 CellData->u.KeyValue.DataLength = DataSize;
237 ASSERT(HvIsCellDirty(Hive, CellData->u.KeyValue.Data));
238 }
239 else
240 {
241 /* This is a small key, set the data directly inside */
243 CellData->u.KeyValue.Data = SmallData;
244 }
245
246 /* Set the type now */
247 CellData->u.KeyValue.Type = Type;
248
249 /* Add this value cell to the child list */
251 ValueCell,
252 Index,
253 StorageType,
254 &Parent->ValueList);
255
256 /* If we failed, free the entire cell, including the data */
257 if (!NT_SUCCESS(Status))
258 {
259 /* Overwrite the status with a known one */
260 CmpFreeValue(Hive, ValueCell);
262 }
263
264 /* Return Status */
265 return Status;
266}
#define CM_KEY_VALUE_SIGNATURE
Definition: cmdata.h:24
#define VALUE_COMP_NAME
Definition: cmdata.h:44
USHORT NTAPI CmpCopyName(IN PHHIVE Hive, OUT PWCHAR Destination, IN PCUNICODE_STRING Source)
Definition: cmname.c:21
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PCUNICODE_STRING Name)
Definition: cmname.c:74
NTSTATUS NTAPI CmpSetValueDataNew(IN PHHIVE Hive, IN PVOID Data, IN ULONG DataSize, IN HSTORAGE_TYPE StorageType, IN HCELL_INDEX ValueCell, OUT PHCELL_INDEX DataCell)
Definition: cmvalue.c:289
NTSTATUS NTAPI CmpAddValueToList(IN PHHIVE Hive, IN HCELL_INDEX ValueCell, IN ULONG Index, IN HSTORAGE_TYPE StorageType, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:207
union _CELL_DATA::@4307 u
CM_KEY_VALUE KeyValue
Definition: cmdata.h:201
USHORT Signature
Definition: cmdata.h:124
ULONG Type
Definition: cmdata.h:128
HCELL_INDEX Data
Definition: cmdata.h:127
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:131
USHORT NameLength
Definition: cmdata.h:125
USHORT Flags
Definition: cmdata.h:129
ULONG DataLength
Definition: cmdata.h:126

Referenced by CmSetValueKey().

◆ CmpUnlinkHiveFromMaster()

static BOOLEAN NTAPI CmpUnlinkHiveFromMaster ( IN PCMHIVE  CmHive,
IN HCELL_INDEX  Cell 
)
static

Definition at line 2169 of file cmapi.c.

2171{
2172 PCELL_DATA CellData;
2173 HCELL_INDEX LinkCell;
2175
2176 DPRINT("CmpUnlinkHiveFromMaster()\n");
2177
2178 /* Get the cell data */
2179 CellData = HvGetCell(&CmHive->Hive, Cell);
2180 if (CellData == NULL)
2181 return FALSE;
2182
2183 /* Get the link cell and release the current cell */
2184 LinkCell = CellData->u.KeyNode.Parent;
2185 HvReleaseCell(&CmHive->Hive, Cell);
2186
2187 /* Remove the link cell from the master hive */
2190 LinkCell,
2191 TRUE);
2193 if (!NT_SUCCESS(Status))
2194 {
2195 DPRINT1("CmpFreeKeyByCell() failed (Status 0x%08lx)\n", Status);
2196 return FALSE;
2197 }
2198
2199 /* Remove the hive from the list */
2201 RemoveEntryList(&CmHive->HiveList);
2203
2204 return TRUE;
2205}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
CM_KEY_NODE KeyNode
Definition: cmdata.h:200

Referenced by CmUnloadKey().

◆ CmQueryKey()

NTSTATUS NTAPI CmQueryKey ( _In_ PCM_KEY_CONTROL_BLOCK  Kcb,
_In_ KEY_INFORMATION_CLASS  KeyInformationClass,
_Out_opt_ PVOID  KeyInformation,
_In_ ULONG  Length,
_Out_ PULONG  ResultLength 
)

Definition at line 1614 of file cmapi.c.

1619{
1621 PHHIVE Hive;
1623 HV_TRACK_CELL_REF CellReferences = {0};
1624
1625 /* Acquire hive lock */
1627
1628 /* Lock KCB shared */
1630
1631 /* Don't touch deleted keys */
1632 if (Kcb->Delete)
1633 {
1634 /* Fail */
1636 goto Quickie;
1637 }
1638
1639 /* Data can be user-mode, use SEH */
1640 _SEH2_TRY
1641 {
1642 /* Check what class we got */
1643 switch (KeyInformationClass)
1644 {
1645 /* Typical information */
1646 case KeyFullInformation:
1648 case KeyNodeInformation:
1649 {
1650 /* Get the hive and parent */
1651 Hive = Kcb->KeyHive;
1652 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1653 ASSERT(Parent);
1654
1655 /* Track cell references */
1656 if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
1657 {
1658 /* Not enough memory to track references */
1660 }
1661 else
1662 {
1663 /* Call the internal API */
1664 Status = CmpQueryKeyData(Hive,
1665 Parent,
1667 KeyInformation,
1668 Length,
1669 ResultLength);
1670 }
1671 break;
1672 }
1673
1675 {
1676 /* Call the internal API */
1678 KeyInformation,
1679 Length,
1680 ResultLength);
1681 break;
1682 }
1683
1685 {
1686 /* Call the internal API */
1688 KeyInformation,
1689 Length,
1690 ResultLength);
1691 break;
1692 }
1693
1694 case KeyNameInformation:
1695 {
1696 /* Call the internal API */
1698 KeyInformation,
1699 Length,
1700 ResultLength);
1701 break;
1702 }
1703
1704 /* Illegal classes */
1705 default:
1706 {
1707 /* Print message and fail */
1708 DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
1710 break;
1711 }
1712 }
1713 }
1715 {
1716 /* Fail with exception code */
1718 _SEH2_YIELD(goto Quickie);
1719 }
1720 _SEH2_END;
1721
1722Quickie:
1723 /* Release references */
1724 HvReleaseFreeCellRefArray(&CellReferences);
1725
1726 /* Release locks */
1727 CmpReleaseKcbLock(Kcb);
1729 return Status;
1730}
static NTSTATUS CmpQueryKeyDataFromCache(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1362
static NTSTATUS CmpQueryFlagsInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo, _In_ ULONG Length, _In_ PULONG ResultLength)
Definition: cmapi.c:1497
static NTSTATUS CmpQueryNameInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1518
@ KeyFlagsInformation
Definition: winternl.h:833
@ KeyCachedInformation
Definition: winternl.h:832
@ KeyNameInformation
Definition: winternl.h:831
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240

Referenced by NtQueryKey().

◆ CmQueryValueKey()

NTSTATUS NTAPI CmQueryValueKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN UNICODE_STRING  ValueName,
IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
IN PVOID  KeyValueInformation,
IN ULONG  Length,
IN PULONG  ResultLength 
)

Definition at line 1074 of file cmapi.c.

1080{
1083 ULONG Index;
1084 BOOLEAN ValueCached = FALSE;
1085 PCM_CACHED_VALUE *CachedValue;
1086 HCELL_INDEX CellToRelease;
1088 PHHIVE Hive;
1089 PAGED_CODE();
1090
1091 /* Acquire hive lock */
1093
1094 /* Lock the KCB shared */
1096
1097 /* Don't touch deleted keys */
1098DoAgain:
1099 if (Kcb->Delete)
1100 {
1101 /* Undo everything */
1102 CmpReleaseKcbLock(Kcb);
1104 return STATUS_KEY_DELETED;
1105 }
1106
1107 /* We don't deal with this yet */
1108 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1109 {
1110 /* Shouldn't happen */
1111 ASSERT(FALSE);
1112 }
1113
1114 /* Get the hive */
1115 Hive = Kcb->KeyHive;
1116
1117 /* Find the key value */
1119 &ValueName,
1120 &CachedValue,
1121 &Index,
1122 &ValueData,
1123 &ValueCached,
1124 &CellToRelease);
1126 {
1127 /* Check if we need an exclusive lock */
1128 ASSERT(CellToRelease == HCELL_NIL);
1129 ASSERT(ValueData == NULL);
1130
1131 /* Try with exclusive KCB lock */
1133 goto DoAgain;
1134 }
1135
1136 if (Result == SearchSuccess)
1137 {
1138 /* Sanity check */
1139 ASSERT(ValueData != NULL);
1140
1141 /* User data, protect against exceptions */
1142 _SEH2_TRY
1143 {
1144 /* Query the information requested */
1146 CachedValue,
1147 ValueData,
1148 ValueCached,
1150 KeyValueInformation,
1151 Length,
1153 &Status);
1155 {
1156 /* Release the value cell */
1157 if (CellToRelease != HCELL_NIL)
1158 {
1159 HvReleaseCell(Hive, CellToRelease);
1160 CellToRelease = HCELL_NIL;
1161 }
1162
1163 /* Try with exclusive KCB lock */
1165 _SEH2_YIELD(goto DoAgain);
1166 }
1167 }
1169 {
1171 }
1172 _SEH2_END;
1173 }
1174 else
1175 {
1176 /* Failed to find the value */
1178 }
1179
1180 /* If we have a cell to release, do so */
1181 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1182
1183 /* Release locks */
1184 CmpReleaseKcbLock(Kcb);
1186 return Status;
1187}
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)
Definition: cmvalche.c:194

Referenced by NtQueryValueKey().

◆ CmSaveKey()

NTSTATUS NTAPI CmSaveKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN HANDLE  FileHandle,
IN ULONG  Flags 
)

Definition at line 2661 of file cmapi.c.

2664{
2665#if DBG
2666 CM_CHECK_REGISTRY_STATUS CheckStatus;
2667 PCMHIVE HiveToValidate = NULL;
2668#endif
2670 PCMHIVE KeyHive = NULL;
2671 PAGED_CODE();
2672
2673 DPRINT("CmSaveKey(0x%08X, 0x%08X, %lu)\n", Kcb, FileHandle, Flags);
2674
2675 /* Lock the registry and KCB */
2678
2679#if DBG
2680 /* Get the hive for validation */
2681 HiveToValidate = (PCMHIVE)Kcb->KeyHive;
2682#endif
2683
2684 if (Kcb->Delete)
2685 {
2686 /* The source key has been deleted, do nothing */
2688 goto Cleanup;
2689 }
2690
2691 if (Kcb->KeyHive == &CmiVolatileHive->Hive)
2692 {
2693 /* Keys that are directly in the master hive can't be saved */
2695 goto Cleanup;
2696 }
2697
2698#if DBG
2699 /* Make sure this control block has a sane hive */
2701 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2702#endif
2703
2704 /* Create a new hive that will hold the key */
2705 Status = CmpInitializeHive(&KeyHive,
2709 NULL,
2710 NULL,
2711 NULL,
2712 NULL,
2713 NULL,
2714 NULL,
2716 if (!NT_SUCCESS(Status)) goto Cleanup;
2717
2718 /* Copy the key recursively into the new hive */
2719 Status = CmpDeepCopyKey(Kcb->KeyHive,
2720 Kcb->KeyCell,
2721 &KeyHive->Hive,
2722 Stable,
2723 &KeyHive->Hive.BaseBlock->RootCell);
2724 if (!NT_SUCCESS(Status)) goto Cleanup;
2725
2726 /* Set the primary handle of the hive */
2728
2729 /* Dump the hive into the file */
2730 HvWriteHive(&KeyHive->Hive);
2731
2732Cleanup:
2733
2734 /* Free the hive */
2735 if (KeyHive) CmpDestroyHive(KeyHive);
2736
2737#if DBG
2738 if (NT_SUCCESS(Status))
2739 {
2740 /* Before we say goodbye, make sure the hive is still OK */
2742 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2743 }
2744#endif
2745
2746 /* Release the locks */
2747 CmpReleaseKcbLock(Kcb);
2749
2750 return Status;
2751}
NTSTATUS NTAPI CmpDeepCopyKey(IN PHHIVE SourceHive, IN HCELL_INDEX SrcKeyCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType, OUT PHCELL_INDEX DestKeyCell OPTIONAL)
Definition: cmapi.c:2644
BOOLEAN CMAPI HvWriteHive(PHHIVE RegistryHive)
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
#define HINIT_CREATE
Definition: hivedata.h:13
#define HIVE_VOLATILE
Definition: hivedata.h:23
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
if(dx< 0)
Definition: linetemp.h:194
NTSTATUS NTAPI CmpInitializeHive(_Out_ PCMHIVE *CmHive, _In_ ULONG OperationType, _In_ ULONG HiveFlags, _In_ ULONG FileType, _In_opt_ PVOID HiveData, _In_ HANDLE Primary, _In_ HANDLE Log, _In_ HANDLE External, _In_ HANDLE Alternate, _In_opt_ PCUNICODE_STRING FileName, _In_ ULONG CheckFlags)
Definition: cminit.c:19
HANDLE FileHandles[HFILE_TYPE_MAX]
Definition: cmlib.h:318
HCELL_INDEX RootCell
Definition: hivedata.h:168
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145

Referenced by NtSaveKeyEx().

◆ CmSaveMergedKeys()

NTSTATUS NTAPI CmSaveMergedKeys ( IN PCM_KEY_CONTROL_BLOCK  HighKcb,
IN PCM_KEY_CONTROL_BLOCK  LowKcb,
IN HANDLE  FileHandle 
)

Definition at line 2755 of file cmapi.c.

2758{
2759#if DBG
2760 CM_CHECK_REGISTRY_STATUS CheckStatus;
2761 PCMHIVE LowHiveToValidate = NULL;
2762 PCMHIVE HighHiveToValidate = NULL;
2763#endif
2764 PCMHIVE KeyHive = NULL;
2766
2767 PAGED_CODE();
2768
2769 DPRINT("CmSaveKey(%p, %p, %p)\n", HighKcb, LowKcb, FileHandle);
2770
2771 /* Lock the registry and the KCBs */
2773 CmpAcquireKcbLockShared(HighKcb);
2775
2776#if DBG
2777 /* Get the high and low hives for validation */
2778 HighHiveToValidate = (PCMHIVE)HighKcb->KeyHive;
2779 LowHiveToValidate = (PCMHIVE)LowKcb->KeyHive;
2780#endif
2781
2782 if (LowKcb->Delete || HighKcb->Delete)
2783 {
2784 /* The source key has been deleted, do nothing */
2786 goto done;
2787 }
2788
2789#if DBG
2790 /* Make sure that both the high and low precedence hives are OK */
2792 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2794 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2795#endif
2796
2797 /* Create a new hive that will hold the key */
2798 Status = CmpInitializeHive(&KeyHive,
2802 NULL,
2803 NULL,
2804 NULL,
2805 NULL,
2806 NULL,
2807 NULL,
2809 if (!NT_SUCCESS(Status))
2810 goto done;
2811
2812 /* Copy the low precedence key recursively into the new hive */
2813 Status = CmpDeepCopyKey(LowKcb->KeyHive,
2814 LowKcb->KeyCell,
2815 &KeyHive->Hive,
2816 Stable,
2817 &KeyHive->Hive.BaseBlock->RootCell);
2818 if (!NT_SUCCESS(Status))
2819 goto done;
2820
2821 /* Copy the high precedence key recursively into the new hive */
2822 Status = CmpDeepCopyKey(HighKcb->KeyHive,
2823 HighKcb->KeyCell,
2824 &KeyHive->Hive,
2825 Stable,
2826 &KeyHive->Hive.BaseBlock->RootCell);
2827 if (!NT_SUCCESS(Status))
2828 goto done;
2829
2830 /* Set the primary handle of the hive */
2832
2833 /* Dump the hive into the file */
2834 HvWriteHive(&KeyHive->Hive);
2835
2836done:
2837 /* Free the hive */
2838 if (KeyHive)
2839 CmpDestroyHive(KeyHive);
2840
2841#if DBG
2842 if (NT_SUCCESS(Status))
2843 {
2844 /* Check those hives again before we say goodbye */
2846 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2848 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2849 }
2850#endif
2851
2852 /* Release the locks */
2853 CmpReleaseKcbLock(LowKcb);
2854 CmpReleaseKcbLock(HighKcb);
2856
2857 return Status;
2858}

Referenced by NtSaveMergedKeys().

◆ CmSetValueKey()

NTSTATUS NTAPI CmSetValueKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN PUNICODE_STRING  ValueName,
IN ULONG  Type,
IN PVOID  Data,
IN ULONG  DataLength 
)

Definition at line 643 of file cmapi.c.

648{
649 PHHIVE Hive = NULL;
652 HCELL_INDEX CurrentChild, Cell;
655 ULONG Count, ChildIndex, SmallData, Storage;
656 VALUE_SEARCH_RETURN_TYPE SearchResult;
657 BOOLEAN FirstTry = TRUE, FlusherLocked = FALSE;
658 HCELL_INDEX ParentCell = HCELL_NIL, ChildCell = HCELL_NIL;
659
660 /* Acquire hive and KCB lock */
663
664 /* Sanity check */
665 ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL);
666
667 /* Don't touch deleted KCBs */
668DoAgain:
669 if (Kcb->Delete)
670 {
671 /* Fail */
673 goto Quickie;
674 }
675
676 /* Don't let anyone mess with symlinks */
677 if ((Kcb->Flags & KEY_SYM_LINK) &&
678 ((Type != REG_LINK) ||
679 !(ValueName) ||
681 {
682 /* Invalid modification of a symlink key */
684 goto Quickie;
685 }
686
687 /* Check if this is the first attempt */
688 if (FirstTry)
689 {
690 /* Search for the value in the cache */
691 SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
692 ValueName,
693 Type,
694 Data,
695 DataLength);
696 if (SearchResult == SearchNeedExclusiveLock)
697 {
698 /* Try again with the exclusive lock */
700 goto DoAgain;
701 }
702 else if (SearchResult == SearchSuccess)
703 {
704 /* We don't actually need to do anything! */
706 goto Quickie;
707 }
708
709 /* We need the exclusive KCB lock now */
710 if (!CmpIsKcbLockedExclusive(Kcb) &&
712 {
713 /* Acquire exclusive lock */
715 }
716
717 /* Cache lookup failed, so don't try it next time */
718 FirstTry = FALSE;
719
720 /* Now grab the flush lock since the key will be modified */
721 ASSERT(FlusherLocked == FALSE);
722 CmpLockHiveFlusherShared((PCMHIVE)Kcb->KeyHive);
723 FlusherLocked = TRUE;
724 goto DoAgain;
725 }
726 else
727 {
728 /* Get pointer to key cell */
729 Hive = Kcb->KeyHive;
730 Cell = Kcb->KeyCell;
731
732 /* Get the parent */
733 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
734 ASSERT(Parent);
735 ParentCell = Cell;
736
737 /* Prepare to scan the key node */
738 Count = Parent->ValueList.Count;
739 Found = FALSE;
740 if (Count > 0)
741 {
742 /* Try to find the existing name */
744 &Parent->ValueList,
745 ValueName,
746 &ChildIndex,
747 &CurrentChild);
748 if (!Result)
749 {
750 /* Fail */
752 goto Quickie;
753 }
754
755 /* Check if we found something */
756 if (CurrentChild != HCELL_NIL)
757 {
758 /* Release existing child */
759 if (ChildCell != HCELL_NIL)
760 {
761 HvReleaseCell(Hive, ChildCell);
762 ChildCell = HCELL_NIL;
763 }
764
765 /* Get its value */
766 Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
767 if (!Value)
768 {
769 /* Fail */
771 goto Quickie;
772 }
773
774 /* Remember that we found it */
775 ChildCell = CurrentChild;
776 Found = TRUE;
777 }
778 }
779 else
780 {
781 /* No child list, we'll need to add it */
782 ChildIndex = 0;
783 }
784 }
785
786 /* Should only get here on the second pass */
788
789 /* The KCB must be locked exclusive at this point */
791
792 /* Mark the cell dirty */
793 if (!HvMarkCellDirty(Hive, Cell, FALSE))
794 {
795 /* Not enough log space, fail */
797 goto Quickie;
798 }
799
800 /* Get the storage type */
801 Storage = HvGetCellType(Cell);
802
803 /* Check if this is small data */
804 SmallData = 0;
805 if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
806 {
807 /* Need SEH because user data may be invalid */
809 {
810 /* Copy it */
811 RtlCopyMemory(&SmallData, Data, DataLength);
812 }
814 {
815 /* Return failure code */
817 _SEH2_YIELD(goto Quickie);
818 }
819 _SEH2_END;
820 }
821
822 /* Check if we didn't find a matching key */
823 if (!Found)
824 {
825 /* Call the internal routine */
827 Parent,
828 ValueName,
829 ChildIndex,
830 Type,
831 Data,
833 Storage,
834 SmallData);
835 }
836 else
837 {
838 /* Call the internal routine */
840 CurrentChild,
841 Value,
842 Type,
843 Data,
845 Storage,
846 SmallData);
847 }
848
849 /* Check for success */
850 if (NT_SUCCESS(Status))
851 {
852 /* Check if the maximum value name length changed */
853 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
854 if (Parent->MaxValueNameLen < ValueName->Length)
855 {
856 /* Set the new values */
857 Parent->MaxValueNameLen = ValueName->Length;
858 Kcb->KcbMaxValueNameLen = ValueName->Length;
859 }
860
861 /* Check if the maximum data length changed */
862 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
863 if (Parent->MaxValueDataLen < DataLength)
864 {
865 /* Update it */
866 Parent->MaxValueDataLen = DataLength;
867 Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen;
868 }
869
870 /* Save the write time */
871 KeQuerySystemTime(&Parent->LastWriteTime);
872 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
873
874 /* Check if the cell is cached */
875 if (Found && CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
876 {
877 /* Shouldn't happen */
878 ASSERT(FALSE);
879 }
880 else
881 {
882 /* Cleanup the value cache */
884
885 /* Sanity checks */
886 ASSERT(!CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList));
887 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
888
889 /* Set the value cache */
890 Kcb->ValueCache.Count = Parent->ValueList.Count;
891 Kcb->ValueCache.ValueList = Parent->ValueList.List;
892 }
893
894 /* Notify registered callbacks */
895 CmpReportNotify(Kcb,
896 Hive,
897 Kcb->KeyCell,
899 }
900
901 /* Release the cells */
902Quickie:
903 if ((ParentCell != HCELL_NIL) && Hive) HvReleaseCell(Hive, ParentCell);
904 if ((ChildCell != HCELL_NIL) && Hive) HvReleaseCell(Hive, ChildCell);
905
906 /* Release the locks */
907 if (FlusherLocked) CmpUnlockHiveFlusher((PCMHIVE)Hive);
910 return Status;
911}
return Found
Definition: dirsup.c:1270
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
#define CmpIsKcbLockedExclusive(k)
Definition: cm_x.h:88
#define CMP_ASSERT_KCB_LOCK(k)
Definition: cm_x.h:261
FORCEINLINE BOOLEAN CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
Definition: cm_x.h:156
NTSTATUS NTAPI CmpSetValueKeyExisting(IN PHHIVE Hive, IN HCELL_INDEX OldChild, IN PCM_KEY_VALUE Value, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG TempData)
Definition: cmapi.c:270
NTSTATUS NTAPI CmpSetValueKeyNew(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PUNICODE_STRING ValueName, IN ULONG Index, IN ULONG Type, IN PVOID Data, IN ULONG DataSize, IN ULONG StorageType, IN ULONG SmallData)
Definition: cmapi.c:146
UNICODE_STRING CmSymbolicLinkValueName
Definition: cmdata.c:52
#define KEY_SYM_LINK
Definition: cmdata.h:34
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)
Definition: cmvalche.c:700
#define HvGetCellType(Cell)
Definition: hivedata.h:120
static IStorage Storage
Definition: ole2.c:3548
int Count
Definition: noreturn.cpp:7
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define REG_LINK
Definition: nt_native.h:1500
@ FirstTry
Definition: copy.c:25
UINT32 Length
Definition: actbl.h:109

Referenced by NtSetValueKey().

◆ CmUnloadKey()

NTSTATUS NTAPI CmUnloadKey ( IN PCM_KEY_CONTROL_BLOCK  Kcb,
IN ULONG  Flags 
)

NOTE: The following code is mostly equivalent to what we "call" CmpDestroyHive()

Definition at line 2209 of file cmapi.c.

2211{
2212 PHHIVE Hive;
2213 PCMHIVE CmHive;
2214 HCELL_INDEX Cell;
2215
2216 DPRINT("CmUnloadKey(%p, %lx)\n", Kcb, Flags);
2217
2218 /* Get the hive */
2219 Hive = Kcb->KeyHive;
2220 Cell = Kcb->KeyCell;
2221 CmHive = (PCMHIVE)Hive;
2222
2223 /* Fail if the key is not a hive root key */
2224 if (Cell != Hive->BaseBlock->RootCell)
2225 {
2226 DPRINT1("Key is not a hive root key!\n");
2228 }
2229
2230 /* Fail if we try to unload the master hive */
2231 if (CmHive == CmiVolatileHive)
2232 {
2233 DPRINT1("Do not try to unload the master hive!\n");
2235 }
2236
2237 /* Mark this hive as being unloaded */
2239
2240 /* Search for any opened keys in this hive, and take an appropriate action */
2241 if (Kcb->RefCount > 1)
2242 {
2243 if (Flags != REG_FORCE_UNLOAD)
2244 {
2245 if (CmpEnumerateOpenSubKeys(Kcb, FALSE, TRUE, FALSE) != 0)
2246 {
2247 /* There are open subkeys but we don't force hive unloading, fail */
2248 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2249 return STATUS_CANNOT_DELETE;
2250 }
2251 }
2252 else
2253 {
2254 if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE, TRUE) != 0)
2255 {
2256 /* There are open subkeys that we cannot force to unload, fail */
2257 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2258 return STATUS_CANNOT_DELETE;
2259 }
2260 }
2261 }
2262
2263 /* Set the loading flag */
2264 CmHive->HiveIsLoading = TRUE;
2265
2266 /* Flush the hive */
2267 CmFlushKey(Kcb, TRUE);
2268
2269 /* Unlink the hive from the master hive */
2270 if (!CmpUnlinkHiveFromMaster(CmHive, Cell))
2271 {
2272 DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
2273
2274 /* Remove the unloading flag */
2275 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2276
2277 /* Reset the loading flag */
2278 CmHive->HiveIsLoading = FALSE;
2279
2280 /* Return failure */
2282 }
2283
2284 /* Flush any notifications if we force hive unloading */
2285 if (Flags == REG_FORCE_UNLOAD)
2286 CmpFlushNotifiesOnKeyBodyList(Kcb, TRUE); // Lock is already held
2287
2288 /* Clean up information we have on the subkey */
2289 CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
2290
2291 /* Set the KCB in delete mode and remove it */
2292 Kcb->Delete = TRUE;
2294
2295 if (Flags != REG_FORCE_UNLOAD)
2296 {
2297 /* Release the KCB locks */
2298 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
2299
2300 /* Release the hive loading lock */
2302 }
2303
2304 /* Release hive lock */
2306
2307 /* Close file handles */
2308 CmpCloseHiveFiles(CmHive);
2309
2310 /* Remove the hive from the hive file list */
2312
2317 /* Destroy the security descriptor cache */
2319
2320 /* Destroy the view list */
2321 CmpDestroyHiveViewList(CmHive);
2322
2323 /* Delete the flusher lock */
2326
2327 /* Delete the view lock */
2329
2330 /* Free the hive storage */
2331 HvFree(Hive);
2332
2333 /* Free the hive */
2334 CmpFree(CmHive, TAG_CM);
2335
2336 return STATUS_SUCCESS;
2337}
#define REG_FORCE_UNLOAD
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
static BOOLEAN NTAPI CmpUnlinkHiveFromMaster(IN PCMHIVE CmHive, IN HCELL_INDEX Cell)
Definition: cmapi.c:2169
ULONG NTAPI CmpEnumerateOpenSubKeys(_In_ PCM_KEY_CONTROL_BLOCK RootKcb, _In_ BOOLEAN LockHeldExclusively, _In_ BOOLEAN RemoveEmptyCacheEntries, _In_ BOOLEAN DereferenceOpenedEntries)
Definition: cmapi.c:2341
NTSTATUS NTAPI CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN ExclusiveLock)
Definition: cmapi.c:1937
VOID NTAPI CmpRemoveFromHiveFileList(IN PCMHIVE Hive)
Definition: cmhvlist.c:254
#define TAG_CMHIVE
Definition: cmlib.h:214
#define TAG_CM
Definition: cmlib.h:212
VOID CMAPI HvFree(PHHIVE RegistryHive)
VOID NTAPI CmpDestroyHiveViewList(IN PCMHIVE Hive)
Definition: cmmapvw.c:35
VOID NTAPI CmpDestroySecurityCache(IN PCMHIVE Hive)
Definition: cmsecach.c:41
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
PERESOURCE FlusherLock
Definition: cmlib.h:327

Referenced by NtUnloadKey2().