ReactOS 0.4.15-dev-7089-gea8a49d
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 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 1824 of file cmapi.c.

1825{
1827 PHHIVE Hive;
1829 HCELL_INDEX Cell, ParentCell;
1831
1832 /* Acquire hive lock */
1834
1835 /* Get the kcb */
1836 Kcb = KeyBody->KeyControlBlock;
1837
1838 /* Don't allow deleting the root */
1839 if (!Kcb->ParentKcb)
1840 {
1841 /* Fail */
1843 return STATUS_CANNOT_DELETE;
1844 }
1845
1846 /* Lock parent and child */
1848
1849 /* Check if we're already being deleted */
1850 if (Kcb->Delete)
1851 {
1852 /* Don't do it twice */
1854 goto Quickie;
1855 }
1856
1857 /* Get the hive and node */
1858 Hive = Kcb->KeyHive;
1859 Cell = Kcb->KeyCell;
1860
1861 /* Lock flushes */
1863
1864 /* Get the key node */
1865 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
1866 ASSERT(Node);
1867
1868 /* Sanity check */
1869 ASSERT(Node->Flags == Kcb->Flags);
1870
1871 /* Check if we don't have any children */
1872 if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) &&
1873 !(Node->Flags & KEY_NO_DELETE))
1874 {
1875 /* Send notification to registered callbacks */
1876 CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
1877
1878 /* Get the parent and free the cell */
1879 ParentCell = Node->Parent;
1880 Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
1881 if (NT_SUCCESS(Status))
1882 {
1883 /* Flush any notifications */
1885
1886 /* Clean up information we have on the subkey */
1888
1889 /* Get the parent node */
1890 Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell);
1891 if (Parent)
1892 {
1893 /* Update the maximum name length */
1894 Kcb->ParentKcb->KcbMaxNameLen = (USHORT)Parent->MaxNameLen;
1895
1896 /* Make sure we're dirty */
1897 ASSERT(HvIsCellDirty(Hive, ParentCell));
1898
1899 /* Update the write time */
1900 KeQuerySystemTime(&Parent->LastWriteTime);
1901 Kcb->ParentKcb->KcbLastWriteTime = Parent->LastWriteTime;
1902
1903 /* Release the cell */
1904 HvReleaseCell(Hive, ParentCell);
1905 }
1906
1907 /* Set the KCB in delete mode and remove it */
1908 Kcb->Delete = TRUE;
1910
1911 /* Clear the cell */
1912 Kcb->KeyCell = HCELL_NIL;
1913 }
1914 }
1915 else
1916 {
1917 /* Fail */
1919 }
1920
1921 /* Release the cell */
1922 HvReleaseCell(Hive, Cell);
1923
1924 /* Release flush lock */
1926
1927 /* Release the KCB locks */
1928Quickie:
1929 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
1930
1931 /* Release hive lock */
1933 return Status;
1934}
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:455
BOOLEAN CMAPI HvIsCellDirty(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:153
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:452
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:2050
VOID NTAPI CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2073
VOID NTAPI CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, IN ULONG ConvKey2)
Definition: cmsysini.c:2102
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1964
VOID NTAPI CmpLockHiveFlusherShared(IN PCMHIVE Hive)
Definition: cmsysini.c:2011
VOID NTAPI CmpUnlockHiveFlusher(IN PCMHIVE Hive)
Definition: cmsysini.c:2022
#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 916 of file cmapi.c.

918{
920 PHHIVE Hive;
922 HCELL_INDEX ChildCell, Cell;
925 ULONG ChildIndex;
927
928 /* Acquire hive lock */
930
931 /* Lock KCB exclusively */
933
934 /* Don't touch deleted keys */
935 if (Kcb->Delete)
936 {
937 /* Undo everything */
940 return STATUS_KEY_DELETED;
941 }
942
943 /* Get the hive and the cell index */
944 Hive = Kcb->KeyHive;
945 Cell = Kcb->KeyCell;
946
947 /* Lock flushes */
949
950 /* Get the parent key node */
951 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
952 ASSERT(Parent);
953
954 /* Get the value list and check if it has any entries */
955 ChildList = &Parent->ValueList;
956 if (ChildList->Count)
957 {
958 /* Try to find this value */
960 ChildList,
961 &ValueName,
962 &ChildIndex,
963 &ChildCell);
964 if (!Result)
965 {
966 /* Fail */
968 goto Quickie;
969 }
970
971 /* Value not found, return error */
972 if (ChildCell == HCELL_NIL) goto Quickie;
973
974 /* We found the value, mark all relevant cells dirty */
975 if (!((HvMarkCellDirty(Hive, Cell, FALSE)) &&
976 (HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE)) &&
977 (HvMarkCellDirty(Hive, ChildCell, FALSE))))
978 {
979 /* Not enough log space, fail */
981 goto Quickie;
982 }
983
984 /* Get the key value */
985 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ChildCell);
986 ASSERT(Value);
987
988 /* Mark it and all related data as dirty */
989 if (!CmpMarkValueDataDirty(Hive, Value))
990 {
991 /* Not enough log space, fail */
993 goto Quickie;
994 }
995
996 /* Sanity checks */
997 ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
998 ASSERT(HvIsCellDirty(Hive, ChildCell));
999
1000 /* Remove the value from the child list */
1001 Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
1002 if (!NT_SUCCESS(Status))
1003 {
1004 /* Set known error */
1006 goto Quickie;
1007 }
1008
1009 /* Remove the value and its data itself */
1010 if (!CmpFreeValue(Hive, ChildCell))
1011 {
1012 /* Failed to free the value, fail */
1014 goto Quickie;
1015 }
1016
1017 /* Set the last write time */
1018 KeQuerySystemTime(&Parent->LastWriteTime);
1019 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
1020
1021 /* Sanity check */
1022 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
1023 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
1024 ASSERT(HvIsCellDirty(Hive, Cell));
1025
1026 /* Check if the value list is empty now */
1027 if (!Parent->ValueList.Count)
1028 {
1029 /* Then clear key node data */
1030 Parent->MaxValueNameLen = 0;
1031 Parent->MaxValueDataLen = 0;
1032 Kcb->KcbMaxValueNameLen = 0;
1033 Kcb->KcbMaxValueDataLen = 0;
1034 }
1035
1036 /* Cleanup the value cache */
1038
1039 /* Sanity checks */
1040 ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
1041 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
1042
1043 /* Set the value cache */
1044 Kcb->ValueCache.Count = ChildList->Count;
1045 Kcb->ValueCache.ValueList = ChildList->List;
1046
1047 /* Notify registered callbacks */
1049
1050 /* Change default Status to success */
1052 }
1053
1054Quickie:
1055 /* Release the parent cell, if any */
1056 if (Parent) HvReleaseCell(Hive, Cell);
1057
1058 /* Check if we had a value */
1059 if (Value)
1060 {
1061 /* Release the child cell */
1062 ASSERT(ChildCell != HCELL_NIL);
1063 HvReleaseCell(Hive, ChildCell);
1064 }
1065
1066 /* Release locks */
1068 CmpReleaseKcbLock(Kcb);
1070 return Status;
1071}
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 1735 of file cmapi.c.

1741{
1743 PHHIVE Hive;
1745 HCELL_INDEX ChildCell;
1746 HV_TRACK_CELL_REF CellReferences = {0};
1747
1748 /* Acquire hive lock */
1750
1751 /* Lock the KCB shared */
1753
1754 /* Don't touch deleted keys */
1755 if (Kcb->Delete)
1756 {
1757 /* Undo everything */
1759 goto Quickie;
1760 }
1761
1762 /* Get the hive and parent */
1763 Hive = Kcb->KeyHive;
1764 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1765 ASSERT(Parent);
1766
1767 /* Get the child cell */
1768 ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
1769
1770 /* Release the parent cell */
1771 HvReleaseCell(Hive, Kcb->KeyCell);
1772
1773 /* Check if we found the child */
1774 if (ChildCell == HCELL_NIL)
1775 {
1776 /* We didn't, fail */
1778 goto Quickie;
1779 }
1780
1781 /* Now get the actual child node */
1782 Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
1783 ASSERT(Child);
1784
1785 /* Track references */
1786 if (!HvTrackCellRef(&CellReferences, Hive, ChildCell))
1787 {
1788 /* Can't allocate memory for tracking */
1790 goto Quickie;
1791 }
1792
1793 /* Data can be user-mode, use SEH */
1794 _SEH2_TRY
1795 {
1796 /* Query the data requested */
1797 Status = CmpQueryKeyData(Hive,
1798 Child,
1800 KeyInformation,
1801 Length,
1802 ResultLength);
1803 }
1805 {
1806 /* Fail with exception code */
1808 _SEH2_YIELD(goto Quickie);
1809 }
1810 _SEH2_END;
1811
1812Quickie:
1813 /* Release references */
1814 HvReleaseFreeCellRefArray(&CellReferences);
1815
1816 /* Release locks */
1817 CmpReleaseKcbLock(Kcb);
1819 return Status;
1820}
#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:376
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:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
_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 1192 of file cmapi.c.

1198{
1200 PHHIVE Hive;
1202 HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL;
1204 BOOLEAN IndexIsCached, ValueIsCached = FALSE;
1205 PCELL_DATA CellData;
1206 PCM_CACHED_VALUE *CachedValue;
1208 PAGED_CODE();
1209
1210 /* Acquire hive lock */
1212
1213 /* Lock the KCB shared */
1215
1216 /* Don't touch deleted keys */
1217DoAgain:
1218 if (Kcb->Delete)
1219 {
1220 /* Undo everything */
1221 CmpReleaseKcbLock(Kcb);
1223 return STATUS_KEY_DELETED;
1224 }
1225
1226 /* Get the hive and parent */
1227 Hive = Kcb->KeyHive;
1228 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1229 ASSERT(Parent);
1230
1231 /* FIXME: Lack of cache? */
1232 if (Kcb->ValueCache.Count != Parent->ValueList.Count)
1233 {
1234 DPRINT1("HACK: Overriding value cache count\n");
1235 Kcb->ValueCache.Count = Parent->ValueList.Count;
1236 }
1237
1238 /* Make sure the index is valid */
1239 if (Index >= Kcb->ValueCache.Count)
1240 {
1241 /* Release the cell and fail */
1242 HvReleaseCell(Hive, Kcb->KeyCell);
1244 goto Quickie;
1245 }
1246
1247 /* We don't deal with this yet */
1248 if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
1249 {
1250 /* Shouldn't happen */
1251 ASSERT(FALSE);
1252 }
1253
1254 /* Find the value list */
1256 &CellData,
1257 &IndexIsCached,
1258 &CellToRelease);
1260 {
1261 /* Check if we need an exclusive lock */
1262 ASSERT(CellToRelease == HCELL_NIL);
1263 HvReleaseCell(Hive, Kcb->KeyCell);
1264
1265 /* Try with exclusive KCB lock */
1267 goto DoAgain;
1268 }
1269 else if (Result != SearchSuccess)
1270 {
1271 /* Sanity check */
1272 ASSERT(CellData == NULL);
1273
1274 /* Release the cell and fail */
1276 goto Quickie;
1277 }
1278
1279 /* Now get the key value */
1281 CellData,
1282 Index,
1283 &CachedValue,
1284 &ValueData,
1285 IndexIsCached,
1286 &ValueIsCached,
1287 &CellToRelease2);
1289 {
1290 /* Cleanup state */
1291 ASSERT(CellToRelease2 == HCELL_NIL);
1292 if (CellToRelease)
1293 {
1294 HvReleaseCell(Hive, CellToRelease);
1295 CellToRelease = HCELL_NIL;
1296 }
1297 HvReleaseCell(Hive, Kcb->KeyCell);
1298
1299 /* Try with exclusive KCB lock */
1301 goto DoAgain;
1302 }
1303 else if (Result != SearchSuccess)
1304 {
1305 /* Sanity check */
1306 ASSERT(ValueData == NULL);
1307
1308 /* Release the cells and fail */
1310 goto Quickie;
1311 }
1312
1313 /* User data, need SEH */
1314 _SEH2_TRY
1315 {
1316 /* Query the information requested */
1318 CachedValue,
1319 ValueData,
1320 ValueIsCached,
1322 KeyValueInformation,
1323 Length,
1325 &Status);
1327 {
1328 /* Cleanup state */
1329 if (CellToRelease2) HvReleaseCell(Hive, CellToRelease2);
1330 HvReleaseCell(Hive, Kcb->KeyCell);
1331 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
1332
1333 /* Try with exclusive KCB lock */
1335 _SEH2_YIELD(goto DoAgain);
1336 }
1337 }
1339 {
1340 /* Get exception code */
1342 }
1343 _SEH2_END;
1344
1345Quickie:
1346 /* If we have a cell to release, do so */
1347 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1348
1349 /* Release the parent cell */
1350 HvReleaseCell(Hive, Kcb->KeyCell);
1351
1352 /* If we have a cell to release, do so */
1353 if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
1354
1355 /* Release locks */
1356 CmpReleaseKcbLock(Kcb);
1358 return Status;
1359}
#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 1938 of file cmapi.c.

1940{
1941 PCMHIVE CmHive;
1942#if DBG
1943 CM_CHECK_REGISTRY_STATUS CheckStatus;
1944#endif
1946 PHHIVE Hive;
1947
1948 /* Ignore flushes until we're ready */
1949 if (CmpNoWrite) return STATUS_SUCCESS;
1950
1951 /* Get the hives */
1952 Hive = Kcb->KeyHive;
1953 CmHive = (PCMHIVE)Hive;
1954
1955 /* Check if this is the master hive */
1956 if (CmHive == CmiVolatileHive)
1957 {
1958 /* Flush all the hives instead */
1960 }
1961 else
1962 {
1963#if DBG
1964 /* Make sure the registry hive we're going to flush is OK */
1966 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
1967#endif
1968
1969 /* Don't touch the hive */
1971
1972 ASSERT(CmHive->ViewLock);
1975
1976 /* Will the hive shrink? */
1977 if (HvHiveWillShrink(Hive))
1978 {
1979 /* I don't believe the current Hv does shrinking */
1980 ASSERT(FALSE);
1981 // CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive);
1982 }
1983 else
1984 {
1985 /* Now we can release views */
1986 ASSERT(CmHive->ViewLock);
1987 // CMP_ASSERT_VIEW_LOCK_OWNED(CmHive);
1989 (CmHive->HiveIsLoading == TRUE) ||
1990 (CmHive->ViewLockOwner == KeGetCurrentThread()) ||
1992 CmHive->ViewLockOwner = NULL;
1994 }
1995
1996 /* Flush only this hive */
1997 if (!HvSyncHive(Hive))
1998 {
1999 /* Fail */
2001 }
2002
2003 /* Release the flush lock */
2004 CmpUnlockHiveFlusher(CmHive);
2005 }
2006
2007 /* Return the status */
2008 return Status;
2009}
BOOLEAN NTAPI CmpDoFlushAll(IN BOOLEAN ForceFlush)
Definition: cmapi.c:82
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:2000
BOOLEAN CmpSpecialBootCondition
Definition: cmsysini.c:26
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
BOOLEAN NTAPI CmpTestRegistryLockExclusive(VOID)
Definition: cmsysini.c:1992
BOOLEAN CmpNoWrite
Definition: cmsysini.c:27
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 2013 of file cmapi.c.

2017{
2018 SECURITY_QUALITY_OF_SERVICE ServiceQos;
2019 SECURITY_CLIENT_CONTEXT ClientSecurityContext;
2022 PCMHIVE CmHive, LoadedHive;
2024 CM_PARSE_CONTEXT ParseContext;
2025
2026 /* Check if we have a trust key */
2027 if (KeyBody)
2028 {
2029 /* Fail */
2030 DPRINT("Trusted classes not yet supported\n");
2031 }
2032
2033 /* Build a service QoS for a security context */
2034 ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2037 ServiceQos.EffectiveOnly = TRUE;
2039 &ServiceQos,
2040 FALSE,
2041 &ClientSecurityContext);
2042 if (!NT_SUCCESS(Status))
2043 {
2044 /* Fail */
2045 DPRINT1("Security context failed\n");
2046 return Status;
2047 }
2048
2049 /* Open the target key */
2050 RtlZeroMemory(&ParseContext, sizeof(ParseContext));
2051 ParseContext.CreateOperation = FALSE;
2052 Status = ObOpenObjectByName(TargetKey,
2054 KernelMode,
2055 NULL,
2056 KEY_READ,
2057 &ParseContext,
2058 &KeyHandle);
2060
2061 /* Open the hive */
2062 Status = CmpCmdHiveOpen(SourceFile,
2063 &ClientSecurityContext,
2064 &Allocate,
2065 &CmHive,
2067
2068 /* Get rid of the security context */
2069 SeDeleteClientSecurity(&ClientSecurityContext);
2070
2071 /* See if we failed */
2072 if (!NT_SUCCESS(Status))
2073 {
2074 /* See if the target already existed */
2075 if (KeyHandle)
2076 {
2077 /* Lock the registry */
2079
2080 /* Check if we are already loaded */
2081 if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive))
2082 {
2083 /* That's okay then */
2084 ASSERT(LoadedHive);
2086 }
2087
2088 /* Release the registry */
2090 }
2091
2092 /* Close the key handle if we had one */
2094 return Status;
2095 }
2096
2097 /* Lock the registry shared */
2099
2100 /* Lock loading */
2102
2103 /* Lock the hive to this thread */
2104 CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
2105 CmHive->CreatorOwner = KeGetCurrentThread();
2106
2107 /* Set flag */
2109
2110 /* Link the hive */
2111 Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
2112 TargetKey->RootDirectory,
2113 CmHive,
2114 Allocate,
2115 TargetKey->SecurityDescriptor);
2116 if (NT_SUCCESS(Status))
2117 {
2118 /* Add to HiveList key */
2119 CmpAddToHiveFileList(CmHive);
2120
2121 /* Sync the hive if necessary */
2122 if (Allocate)
2123 {
2124 /* Sync it under the flusher lock */
2126 HvSyncHive(&CmHive->Hive);
2127 CmpUnlockHiveFlusher(CmHive);
2128 }
2129
2130 /* Release the hive */
2131 CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
2132 CmHive->CreatorOwner = NULL;
2133 }
2134 else
2135 {
2136 DPRINT1("CmpLinkHiveToMaster failed, Status %lx\n", Status);
2137
2138 /* We're touching this hive, set the loading flag */
2139 CmHive->HiveIsLoading = TRUE;
2140
2141 /* Close associated file handles */
2142 CmpCloseHiveFiles(CmHive);
2143
2144 /* Cleanup its resources */
2145 CmpDestroyHive(CmHive);
2146 }
2147
2148 /* Allow loads */
2150
2151 /* Is this first profile load? */
2153 {
2154 /* User is now logged on, set quotas */
2157 }
2158
2159 /* Unlock the registry */
2161
2162 /* Close handle and return */
2164 return Status;
2165}
#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:271
#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:1951
NTSTATUS NTAPI CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, IN HANDLE RootDirectory, IN PCMHIVE RegistryHive, IN BOOLEAN Allocate, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: cmsysini.c:798
BOOLEAN CmpProfileLoaded
Definition: cmsysini.c:29
BOOLEAN CmpWasSetupBoot
Definition: cmsysini.c:28
#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:71
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 2636 of file cmapi.c.

2641{
2642 /* Call the internal function */
2643 return CmpDeepCopyKeyInternal(SourceHive,
2644 SrcKeyCell,
2645 DestinationHive,
2646 HCELL_NIL,
2647 StorageType,
2648 DestKeyCell);
2649}
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:2460

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 2460 of file cmapi.c.

2466{
2468 PCM_KEY_NODE SrcNode;
2469 PCM_KEY_NODE DestNode = NULL;
2470 HCELL_INDEX NewKeyCell = HCELL_NIL;
2471 HCELL_INDEX NewClassCell = HCELL_NIL, NewSecCell = HCELL_NIL;
2472 HCELL_INDEX SubKey, NewSubKey;
2473 ULONG Index, SubKeyCount;
2474
2475 PAGED_CODE();
2476
2477 DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
2478 SourceHive,
2479 SrcKeyCell,
2480 DestinationHive,
2481 Parent,
2482 StorageType,
2483 DestKeyCell);
2484
2485 /* Get the source cell node */
2486 SrcNode = (PCM_KEY_NODE)HvGetCell(SourceHive, SrcKeyCell);
2487 ASSERT(SrcNode);
2488
2489 /* Sanity check */
2491
2492 /* Create a simple copy of the source key */
2493 NewKeyCell = CmpCopyCell(SourceHive,
2494 SrcKeyCell,
2495 DestinationHive,
2496 StorageType);
2497 if (NewKeyCell == HCELL_NIL)
2498 {
2499 /* Not enough storage space */
2501 goto Cleanup;
2502 }
2503
2504 /* Get the destination cell node */
2505 DestNode = (PCM_KEY_NODE)HvGetCell(DestinationHive, NewKeyCell);
2506 ASSERT(DestNode);
2507
2508 /* Set the parent and copy the flags */
2509 DestNode->Parent = Parent;
2510 DestNode->Flags = (SrcNode->Flags & KEY_COMP_NAME); // Keep only the single permanent flag
2511 if (Parent == HCELL_NIL)
2512 {
2513 /* This is the new root node */
2514 DestNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
2515 }
2516
2517 /* Copy the class cell */
2518 if (SrcNode->ClassLength > 0)
2519 {
2520 NewClassCell = CmpCopyCell(SourceHive,
2521 SrcNode->Class,
2522 DestinationHive,
2523 StorageType);
2524 if (NewClassCell == HCELL_NIL)
2525 {
2526 /* Not enough storage space */
2528 goto Cleanup;
2529 }
2530
2531 DestNode->Class = NewClassCell;
2532 DestNode->ClassLength = SrcNode->ClassLength;
2533 }
2534 else
2535 {
2536 DestNode->Class = HCELL_NIL;
2537 DestNode->ClassLength = 0;
2538 }
2539
2540 /* Copy the security cell (FIXME: HACKish poor-man version) */
2541 if (SrcNode->Security != HCELL_NIL)
2542 {
2543 NewSecCell = CmpCopyCell(SourceHive,
2544 SrcNode->Security,
2545 DestinationHive,
2546 StorageType);
2547 if (NewSecCell == HCELL_NIL)
2548 {
2549 /* Not enough storage space */
2551 goto Cleanup;
2552 }
2553 }
2554 DestNode->Security = NewSecCell;
2555
2556 /* Copy the value list */
2557 Status = CmpCopyKeyValueList(SourceHive,
2558 &SrcNode->ValueList,
2559 DestinationHive,
2560 &DestNode->ValueList,
2561 StorageType);
2562 if (!NT_SUCCESS(Status))
2563 goto Cleanup;
2564
2565 /* Clear the invalid subkey index */
2566 DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
2567 DestNode->SubKeyLists[Stable] = DestNode->SubKeyLists[Volatile] = HCELL_NIL;
2568
2569 /* Calculate the total number of subkeys */
2570 SubKeyCount = SrcNode->SubKeyCounts[Stable] + SrcNode->SubKeyCounts[Volatile];
2571
2572 /* Loop through all the subkeys */
2573 for (Index = 0; Index < SubKeyCount; Index++)
2574 {
2575 /* Get the subkey */
2576 SubKey = CmpFindSubKeyByNumber(SourceHive, SrcNode, Index);
2577 ASSERT(SubKey != HCELL_NIL);
2578
2579 /* Call the function recursively for the subkey */
2580 //
2581 // FIXME: Danger!! Kernel stack exhaustion!!
2582 //
2583 Status = CmpDeepCopyKeyInternal(SourceHive,
2584 SubKey,
2585 DestinationHive,
2586 NewKeyCell,
2587 StorageType,
2588 &NewSubKey);
2589 if (!NT_SUCCESS(Status))
2590 goto Cleanup;
2591
2592 /* Add the copy of the subkey to the new key */
2593 if (!CmpAddSubKey(DestinationHive,
2594 NewKeyCell,
2595 NewSubKey))
2596 {
2597 /* Cleanup allocated cell */
2598 HvFreeCell(DestinationHive, NewSubKey);
2599
2601 goto Cleanup;
2602 }
2603 }
2604
2605 /* Set success */
2607
2608Cleanup:
2609
2610 /* Release the cells */
2611 if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
2612 if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
2613
2614 /* Cleanup allocated cells in case of failure */
2615 if (!NT_SUCCESS(Status))
2616 {
2617 if (NewSecCell != HCELL_NIL)
2618 HvFreeCell(DestinationHive, NewSecCell);
2619
2620 if (NewClassCell != HCELL_NIL)
2621 HvFreeCell(DestinationHive, NewClassCell);
2622
2623 if (NewKeyCell != HCELL_NIL)
2624 HvFreeCell(DestinationHive, NewKeyCell);
2625
2626 NewKeyCell = HCELL_NIL;
2627 }
2628
2629 /* Set the cell index if requested and return status */
2630 if (DestKeyCell) *DestKeyCell = NewKeyCell;
2631 return Status;
2632}
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 82 of file cmapi.c.

83{
84 PLIST_ENTRY NextEntry;
85 PCMHIVE Hive;
88
89 /* Make sure that the registry isn't read-only now */
90 if (CmpNoWrite) return TRUE;
91
92 /* Otherwise, acquire the hive list lock and disable force flush */
95
96 /* Loop the hive list */
97 NextEntry = CmpHiveListHead.Flink;
98 while (NextEntry != &CmpHiveListHead)
99 {
100 /* Get the hive */
101 Hive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList);
102 if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
103 {
104 /* Acquire the flusher lock */
106
107 /* Check for illegal state */
108 if ((ForceFlush) && (Hive->UseCount))
109 {
110 /* Registry needs to be locked down */
112 DPRINT1("FIXME: Hive is damaged and needs fixup\n");
113 while (TRUE);
114 }
115
116 /* Only sync if we are forced to or if it won't cause a hive shrink */
117 if ((ForceFlush) || (!HvHiveWillShrink(&Hive->Hive)))
118 {
119 /* Do the sync */
120 Status = HvSyncHive(&Hive->Hive);
121
122 /* If something failed - set the flag and continue looping */
123 if (!NT_SUCCESS(Status)) Result = FALSE;
124 }
125 else
126 {
127 /* We won't flush if the hive might shrink */
128 Result = FALSE;
130 }
131
132 /* Release the flusher lock */
134 }
135
136 /* Try the next entry */
137 NextEntry = NextEntry->Flink;
138 }
139
140 /* Release lock and return */
142 return Result;
143}
#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
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  RemoveEmptyCacheEntries,
IN BOOLEAN  DereferenceOpenedEntries 
)

Definition at line 2343 of file cmapi.c.

2347{
2349 PCM_KEY_CONTROL_BLOCK CachedKcb;
2350 PCM_KEY_CONTROL_BLOCK ParentKcb;
2351 ULONG ParentKeyCount;
2352 ULONG i, j;
2353 ULONG SubKeys = 0;
2354
2355 DPRINT("CmpEnumerateOpenSubKeys() called\n");
2356
2357 /* The root key is the only referenced key. There are no referenced sub keys. */
2358 if (RootKcb->RefCount == 1)
2359 {
2360 DPRINT("Open sub keys: 0\n");
2361 return 0;
2362 }
2363
2364 /* Enumerate all hash lists */
2365 for (i = 0; i < CmpHashTableSize; i++)
2366 {
2367 /* Get the first cache entry */
2369
2370 /* Enumerate all cache entries */
2371 while (Entry)
2372 {
2373 /* Get the KCB of the current cache entry */
2375
2376 /* Check keys only that are subkeys to our root key */
2377 if (CachedKcb->TotalLevels > RootKcb->TotalLevels)
2378 {
2379 /* Calculate the number of parent keys to the root key */
2380 ParentKeyCount = CachedKcb->TotalLevels - RootKcb->TotalLevels;
2381
2382 /* Find a parent key that could be the root key */
2383 ParentKcb = CachedKcb;
2384 for (j = 0; j < ParentKeyCount; j++)
2385 {
2386 ParentKcb = ParentKcb->ParentKcb;
2387 }
2388
2389 /* Check whether the parent is the root key */
2390 if (ParentKcb == RootKcb)
2391 {
2392 DPRINT("Found a sub key, RefCount = %u\n", CachedKcb->RefCount);
2393
2394 if (CachedKcb->RefCount > 0)
2395 {
2396 DPRINT("Found a sub key pointing to '%.*s', RefCount = %u\n",
2397 CachedKcb->NameBlock->NameLength, CachedKcb->NameBlock->Name,
2398 CachedKcb->RefCount);
2399
2400 /* If we dereference opened KCBs, don't touch read-only keys */
2401 if (DereferenceOpenedEntries &&
2402 !(CachedKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
2403 {
2404 /* Registry needs to be locked down */
2406
2407 /* Flush any notifications */
2408 CmpFlushNotifiesOnKeyBodyList(CachedKcb, TRUE); // Lock is already held
2409
2410 /* Clean up information we have on the subkey */
2411 CmpCleanUpSubKeyInfo(CachedKcb->ParentKcb);
2412
2413 /* Get and cache the next cache entry */
2414 // Entry = Entry->NextHash;
2415 Entry = CachedKcb->NextHash;
2416
2417 /* Set the KCB in delete mode and remove it */
2418 CachedKcb->Delete = TRUE;
2419 CmpRemoveKeyControlBlock(CachedKcb);
2420
2421 /* Clear the cell */
2422 CachedKcb->KeyCell = HCELL_NIL;
2423
2424 /* Restart with the next cache entry */
2425 continue;
2426 }
2427 /* Else, the key cannot be dereferenced, and we count it as in use */
2428
2429 /* Count the current hash entry if it is in use */
2430 SubKeys++;
2431 }
2432 else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
2433 {
2434 /* Remove the current key from the delayed close list */
2435 CmpRemoveFromDelayedClose(CachedKcb);
2436
2437 /* Remove the current cache entry */
2438 CmpCleanUpKcbCacheWithLock(CachedKcb, TRUE);
2439
2440 /* Restart, because the hash list has changed */
2442 continue;
2443 }
2444 }
2445 }
2446
2447 /* Get the next cache entry */
2448 Entry = Entry->NextHash;
2449 }
2450 }
2451
2452 if (SubKeys > 0)
2453 DPRINT1("Open sub keys: %u\n", SubKeys);
2454
2455 return SubKeys;
2456}
#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 DPRINT1("ERROR: Hive is frozen\n");
71 while (TRUE);
72 }
73 }
74
75 /* Dereference and return result */
76 ObDereferenceObject(KeyBody);
77 return Loaded;
78 }
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 1498 of file cmapi.c.

1503{
1504 /* Validate the buffer size */
1505 *ResultLength = sizeof(*KeyFlagsInfo);
1506 if (Length < *ResultLength)
1507 {
1509 }
1510
1511 /* Copy the user flags */
1512 KeyFlagsInfo->UserFlags = Kcb->KcbUserFlags;
1513
1514 return STATUS_SUCCESS;
1515}
#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 376 of file cmapi.c.

382{
384 ULONG Size, SizeLeft, MinimumSize, Offset;
385 PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
386 USHORT NameLength;
388
389 /* Check if the value is compressed */
390 if (Node->Flags & KEY_COMP_NAME)
391 {
392 /* Get the compressed name size */
393 NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
394 }
395 else
396 {
397 /* Get the real size */
398 NameLength = Node->NameLength;
399 }
400
401 /* Check what kind of information is being requested */
402 switch (KeyInformationClass)
403 {
404 /* Basic information */
406
407 /* This is the size we need */
409
410 /* And this is the minimum we can work with */
412
413 /* Let the caller know and assume success */
416
417 /* Check if the bufer we got is too small */
418 if (Length < MinimumSize)
419 {
420 /* Let the caller know and fail */
422 break;
423 }
424
425 /* Copy the basic information */
426 Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
427 Info->KeyBasicInformation.TitleIndex = 0;
428 Info->KeyBasicInformation.NameLength = NameLength;
429
430 /* Only the name is left */
431 SizeLeft = Length - MinimumSize;
432 Size = NameLength;
433
434 /* Check if we don't have enough space for the name */
435 if (SizeLeft < Size)
436 {
437 /* Truncate the name we'll return, and tell the caller */
438 Size = SizeLeft;
440 }
441
442 /* Check if this is a compressed key */
443 if (Node->Flags & KEY_COMP_NAME)
444 {
445 /* Copy the compressed name */
446 CmpCopyCompressedName(Info->KeyBasicInformation.Name,
447 SizeLeft,
448 Node->Name,
449 Node->NameLength);
450 }
451 else
452 {
453 /* Otherwise, copy the raw name */
454 RtlCopyMemory(Info->KeyBasicInformation.Name,
455 Node->Name,
456 Size);
457 }
458 break;
459
460 /* Node information */
462
463 /* Calculate the size we need */
465 NameLength +
466 Node->ClassLength;
467
468 /* And the minimum size we can support */
469 MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
470
471 /* Return the size to the caller and assume succes */
474
475 /* Check if the caller's buffer is too small */
476 if (Length < MinimumSize)
477 {
478 /* Let them know, and fail */
480 break;
481 }
482
483 /* Copy the basic information */
484 Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
485 Info->KeyNodeInformation.TitleIndex = 0;
486 Info->KeyNodeInformation.ClassLength = Node->ClassLength;
487 Info->KeyNodeInformation.NameLength = NameLength;
488
489 /* Now the name is left */
490 SizeLeft = Length - MinimumSize;
491 Size = NameLength;
492
493 /* Check if the name can fit entirely */
494 if (SizeLeft < Size)
495 {
496 /* It can't, we'll have to truncate. Tell the caller */
497 Size = SizeLeft;
499 }
500
501 /* Check if the key node name is compressed */
502 if (Node->Flags & KEY_COMP_NAME)
503 {
504 /* Copy the compressed name */
505 CmpCopyCompressedName(Info->KeyNodeInformation.Name,
506 SizeLeft,
507 Node->Name,
508 Node->NameLength);
509 }
510 else
511 {
512 /* It isn't, so copy the raw name */
513 RtlCopyMemory(Info->KeyNodeInformation.Name,
514 Node->Name,
515 Size);
516 }
517
518 /* Check if the node has a class */
519 if (Node->ClassLength > 0)
520 {
521 /* Set the class offset */
523 Offset = ALIGN_UP_BY(Offset, sizeof(ULONG));
524 Info->KeyNodeInformation.ClassOffset = Offset;
525
526 /* Get the class data */
527 ClassData = HvGetCell(Hive, Node->Class);
528 if (ClassData == NULL)
529 {
531 break;
532 }
533
534 /* Check if we can copy anything */
535 if (Length > Offset)
536 {
537 /* Copy the class data */
539 ClassData,
540 min(Node->ClassLength, Length - Offset));
541 }
542
543 /* Check if the buffer was large enough */
544 if (Length < Offset + Node->ClassLength)
545 {
547 }
548
549 /* Release the class cell */
550 HvReleaseCell(Hive, Node->Class);
551 }
552 else
553 {
554 /* It doesn't, so set offset to -1, not 0! */
555 Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
556 }
557 break;
558
559 /* Full information requsted */
561
562 /* This is the size we need */
564 Node->ClassLength;
565
566 /* This is what we can work with */
568
569 /* Return it to caller and assume success */
572
573 /* Check if the caller's buffer is to small */
574 if (Length < MinimumSize)
575 {
576 /* Let them know and fail */
578 break;
579 }
580
581 /* Now copy all the basic information */
582 Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
583 Info->KeyFullInformation.TitleIndex = 0;
584 Info->KeyFullInformation.ClassLength = Node->ClassLength;
585 Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
586 Node->SubKeyCounts[Volatile];
587 Info->KeyFullInformation.Values = Node->ValueList.Count;
588 Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
589 Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
590 Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
591 Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
592
593 /* Check if we have a class */
594 if (Node->ClassLength > 0)
595 {
596 /* Set the class offset */
598 Info->KeyFullInformation.ClassOffset = Offset;
599
600 /* Get the class data */
601 ClassData = HvGetCell(Hive, Node->Class);
602 if (ClassData == NULL)
603 {
605 break;
606 }
607
608 /* Copy the class data */
609 ASSERT(Length >= Offset);
610 RtlCopyMemory(Info->KeyFullInformation.Class,
611 ClassData,
612 min(Node->ClassLength, Length - Offset));
613
614 /* Check if the buffer was large enough */
615 if (Length < Offset + Node->ClassLength)
616 {
618 }
619
620 /* Release the class cell */
621 HvReleaseCell(Hive, Node->Class);
622 }
623 else
624 {
625 /* We don't have a class, so set offset to -1, not 0! */
626 Info->KeyFullInformation.ClassOffset = 0xFFFFFFFF;
627 }
628 break;
629
630 /* Any other class that got sent here is invalid! */
631 default:
632
633 /* Set failure code */
635 break;
636 }
637
638 /* Return status */
639 return Status;
640}
#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 1363 of file cmapi.c.

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

1524{
1525 ULONG NeededLength;
1526 PCM_KEY_CONTROL_BLOCK CurrentKcb;
1527
1528 NeededLength = 0;
1529 CurrentKcb = Kcb;
1530
1531 /* Count the needed buffer size */
1532 while (CurrentKcb)
1533 {
1534 if (CurrentKcb->NameBlock->Compressed)
1535 NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1536 else
1537 NeededLength += CurrentKcb->NameBlock->NameLength;
1538
1539 NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
1540
1541 CurrentKcb = CurrentKcb->ParentKcb;
1542 }
1543
1544 _SEH2_TRY
1545 {
1549 if (Length < *ResultLength)
1550 {
1551 KeyNameInfo->NameLength = NeededLength;
1553 }
1554 }
1556 {
1558 }
1559 _SEH2_END;
1560
1561 /* Do the real copy */
1562 KeyNameInfo->NameLength = 0;
1563 CurrentKcb = Kcb;
1564
1565 _SEH2_TRY
1566 {
1567 while (CurrentKcb)
1568 {
1569 ULONG NameLength;
1570
1571 if (CurrentKcb->NameBlock->Compressed)
1572 {
1573 NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
1574 /* Copy the compressed name */
1575 CmpCopyCompressedName(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1576 NameLength,
1577 CurrentKcb->NameBlock->Name,
1578 CurrentKcb->NameBlock->NameLength);
1579 }
1580 else
1581 {
1582 NameLength = CurrentKcb->NameBlock->NameLength;
1583 /* Otherwise, copy the raw name */
1584 RtlCopyMemory(&KeyNameInfo->Name[(NeededLength - NameLength)/sizeof(WCHAR)],
1585 CurrentKcb->NameBlock->Name,
1586 NameLength);
1587 }
1588
1589 NeededLength -= NameLength;
1590 NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
1591 /* Add path separator */
1592 KeyNameInfo->Name[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
1593 KeyNameInfo->NameLength += NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
1594
1595 CurrentKcb = CurrentKcb->ParentKcb;
1596 }
1597 }
1599 {
1601 }
1602 _SEH2_END;
1603
1604 /* Make sure we copied everything */
1605 ASSERT(NeededLength == 0);
1606 ASSERT(KeyNameInfo->Name[0] == OBJ_NAME_PATH_SEPARATOR);
1607
1608 /* We're done */
1609 return STATUS_SUCCESS;
1610}
#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 271 of file cmapi.c.

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

156{
157 PCELL_DATA CellData;
158 HCELL_INDEX ValueCell;
160
161 /* Check if we already have a value list */
162 if (Parent->ValueList.Count)
163 {
164 /* Then make sure it's valid and dirty it */
165 ASSERT(Parent->ValueList.List != HCELL_NIL);
166 if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE))
167 {
168 /* Fail if we're out of space for log changes */
169 return STATUS_NO_LOG_SPACE;
170 }
171 }
172
173 /* Allocate a value cell */
174 ValueCell = HvAllocateCell(Hive,
176 CmpNameSize(Hive, ValueName),
177 StorageType,
178 HCELL_NIL);
179 if (ValueCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
180
181 /* Get the actual data for it */
182 CellData = HvGetCell(Hive, ValueCell);
183 ASSERT(CellData);
184
185 /* Now we can release it, make sure it's also dirty */
186 HvReleaseCell(Hive, ValueCell);
187 ASSERT(HvIsCellDirty(Hive, ValueCell));
188
189 /* Set it up and copy the name */
192 {
193 /* This can crash since the name is coming from user-mode */
194 CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
195 CellData->u.KeyValue.Name,
196 ValueName);
197 }
199 {
200 /* Fail */
201 DPRINT1("Invalid user data!\n");
202 HvFreeCell(Hive, ValueCell);
204 }
205 _SEH2_END;
206
207 /* Check for compressed name */
208 if (CellData->u.KeyValue.NameLength < ValueName->Length)
209 {
210 /* This is a compressed name */
211 CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
212 }
213 else
214 {
215 /* No flags to set */
216 CellData->u.KeyValue.Flags = 0;
217 }
218
219 /* Check if this is a normal key */
221 {
222 /* Build a data cell for it */
224 Data,
225 DataSize,
226 StorageType,
227 ValueCell,
228 &CellData->u.KeyValue.Data);
229 if (!NT_SUCCESS(Status))
230 {
231 /* We failed, free the cell */
232 HvFreeCell(Hive, ValueCell);
233 return Status;
234 }
235
236 /* Otherwise, set the data length, and make sure the data is dirty */
237 CellData->u.KeyValue.DataLength = DataSize;
238 ASSERT(HvIsCellDirty(Hive, CellData->u.KeyValue.Data));
239 }
240 else
241 {
242 /* This is a small key, set the data directly inside */
244 CellData->u.KeyValue.Data = SmallData;
245 }
246
247 /* Set the type now */
248 CellData->u.KeyValue.Type = Type;
249
250 /* Add this value cell to the child list */
252 ValueCell,
253 Index,
254 StorageType,
255 &Parent->ValueList);
256
257 /* If we failed, free the entire cell, including the data */
258 if (!NT_SUCCESS(Status))
259 {
260 /* Overwrite the status with a known one */
261 CmpFreeValue(Hive, ValueCell);
263 }
264
265 /* Return Status */
266 return Status;
267}
#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
CM_KEY_VALUE KeyValue
Definition: cmdata.h:201
union _CELL_DATA::@4273 u
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 2170 of file cmapi.c.

2172{
2173 PCELL_DATA CellData;
2174 HCELL_INDEX LinkCell;
2176
2177 DPRINT("CmpUnlinkHiveFromMaster()\n");
2178
2179 /* Get the cell data */
2180 CellData = HvGetCell(&CmHive->Hive, Cell);
2181 if (CellData == NULL)
2182 return FALSE;
2183
2184 /* Get the link cell and release the current cell */
2185 LinkCell = CellData->u.KeyNode.Parent;
2186 HvReleaseCell(&CmHive->Hive, Cell);
2187
2188 /* Remove the link cell from the master hive */
2191 LinkCell,
2192 TRUE);
2194 if (!NT_SUCCESS(Status))
2195 {
2196 DPRINT1("CmpFreeKeyByCell() failed (Status 0x%08lx)\n", Status);
2197 return FALSE;
2198 }
2199
2200 /* Remove the hive from the list */
2202 RemoveEntryList(&CmHive->HiveList);
2204
2205 return TRUE;
2206}
#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 1615 of file cmapi.c.

1620{
1622 PHHIVE Hive;
1624 HV_TRACK_CELL_REF CellReferences = {0};
1625
1626 /* Acquire hive lock */
1628
1629 /* Lock KCB shared */
1631
1632 /* Don't touch deleted keys */
1633 if (Kcb->Delete)
1634 {
1635 /* Fail */
1637 goto Quickie;
1638 }
1639
1640 /* Data can be user-mode, use SEH */
1641 _SEH2_TRY
1642 {
1643 /* Check what class we got */
1644 switch (KeyInformationClass)
1645 {
1646 /* Typical information */
1647 case KeyFullInformation:
1649 case KeyNodeInformation:
1650 {
1651 /* Get the hive and parent */
1652 Hive = Kcb->KeyHive;
1653 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
1654 ASSERT(Parent);
1655
1656 /* Track cell references */
1657 if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
1658 {
1659 /* Not enough memory to track references */
1661 }
1662 else
1663 {
1664 /* Call the internal API */
1665 Status = CmpQueryKeyData(Hive,
1666 Parent,
1668 KeyInformation,
1669 Length,
1670 ResultLength);
1671 }
1672 break;
1673 }
1674
1676 {
1677 /* Call the internal API */
1679 KeyInformation,
1680 Length,
1681 ResultLength);
1682 break;
1683 }
1684
1686 {
1687 /* Call the internal API */
1689 KeyInformation,
1690 Length,
1691 ResultLength);
1692 break;
1693 }
1694
1695 case KeyNameInformation:
1696 {
1697 /* Call the internal API */
1699 KeyInformation,
1700 Length,
1701 ResultLength);
1702 break;
1703 }
1704
1705 /* Illegal classes */
1706 default:
1707 {
1708 /* Print message and fail */
1709 DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
1711 break;
1712 }
1713 }
1714 }
1716 {
1717 /* Fail with exception code */
1719 _SEH2_YIELD(goto Quickie);
1720 }
1721 _SEH2_END;
1722
1723Quickie:
1724 /* Release references */
1725 HvReleaseFreeCellRefArray(&CellReferences);
1726
1727 /* Release locks */
1728 CmpReleaseKcbLock(Kcb);
1730 return Status;
1731}
static NTSTATUS CmpQueryKeyDataFromCache(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_CACHED_INFORMATION KeyCachedInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1363
static NTSTATUS CmpQueryFlagsInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo, _In_ ULONG Length, _In_ PULONG ResultLength)
Definition: cmapi.c:1498
static NTSTATUS CmpQueryNameInformation(_In_ PCM_KEY_CONTROL_BLOCK Kcb, _Out_opt_ PKEY_NAME_INFORMATION KeyNameInfo, _In_ ULONG Length, _Out_ PULONG ResultLength)
Definition: cmapi.c:1519
@ 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 1075 of file cmapi.c.

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

2656{
2657#if DBG
2658 CM_CHECK_REGISTRY_STATUS CheckStatus;
2659 PCMHIVE HiveToValidate = NULL;
2660#endif
2662 PCMHIVE KeyHive = NULL;
2663 PAGED_CODE();
2664
2665 DPRINT("CmSaveKey(0x%08X, 0x%08X, %lu)\n", Kcb, FileHandle, Flags);
2666
2667 /* Lock the registry and KCB */
2670
2671#if DBG
2672 /* Get the hive for validation */
2673 HiveToValidate = (PCMHIVE)Kcb->KeyHive;
2674#endif
2675
2676 if (Kcb->Delete)
2677 {
2678 /* The source key has been deleted, do nothing */
2680 goto Cleanup;
2681 }
2682
2683 if (Kcb->KeyHive == &CmiVolatileHive->Hive)
2684 {
2685 /* Keys that are directly in the master hive can't be saved */
2687 goto Cleanup;
2688 }
2689
2690#if DBG
2691 /* Make sure this control block has a sane hive */
2693 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2694#endif
2695
2696 /* Create a new hive that will hold the key */
2697 Status = CmpInitializeHive(&KeyHive,
2701 NULL,
2702 NULL,
2703 NULL,
2704 NULL,
2705 NULL,
2706 NULL,
2708 if (!NT_SUCCESS(Status)) goto Cleanup;
2709
2710 /* Copy the key recursively into the new hive */
2711 Status = CmpDeepCopyKey(Kcb->KeyHive,
2712 Kcb->KeyCell,
2713 &KeyHive->Hive,
2714 Stable,
2715 &KeyHive->Hive.BaseBlock->RootCell);
2716 if (!NT_SUCCESS(Status)) goto Cleanup;
2717
2718 /* Set the primary handle of the hive */
2720
2721 /* Dump the hive into the file */
2722 HvWriteHive(&KeyHive->Hive);
2723
2724Cleanup:
2725
2726 /* Free the hive */
2727 if (KeyHive) CmpDestroyHive(KeyHive);
2728
2729#if DBG
2730 if (NT_SUCCESS(Status))
2731 {
2732 /* Before we say goodbye, make sure the hive is still OK */
2734 ASSERT(CM_CHECK_REGISTRY_SUCCESS(CheckStatus));
2735 }
2736#endif
2737
2738 /* Release the locks */
2739 CmpReleaseKcbLock(Kcb);
2741
2742 return Status;
2743}
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:2636
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 2747 of file cmapi.c.

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

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 644 of file cmapi.c.

649{
650 PHHIVE Hive = NULL;
653 HCELL_INDEX CurrentChild, Cell;
656 ULONG Count, ChildIndex, SmallData, Storage;
657 VALUE_SEARCH_RETURN_TYPE SearchResult;
658 BOOLEAN FirstTry = TRUE, FlusherLocked = FALSE;
659 HCELL_INDEX ParentCell = HCELL_NIL, ChildCell = HCELL_NIL;
660
661 /* Acquire hive and KCB lock */
664
665 /* Sanity check */
666 ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL);
667
668 /* Don't touch deleted KCBs */
669DoAgain:
670 if (Kcb->Delete)
671 {
672 /* Fail */
674 goto Quickie;
675 }
676
677 /* Don't let anyone mess with symlinks */
678 if ((Kcb->Flags & KEY_SYM_LINK) &&
679 ((Type != REG_LINK) ||
680 !(ValueName) ||
682 {
683 /* Invalid modification of a symlink key */
685 goto Quickie;
686 }
687
688 /* Check if this is the first attempt */
689 if (FirstTry)
690 {
691 /* Search for the value in the cache */
692 SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
693 ValueName,
694 Type,
695 Data,
696 DataLength);
697 if (SearchResult == SearchNeedExclusiveLock)
698 {
699 /* Try again with the exclusive lock */
701 goto DoAgain;
702 }
703 else if (SearchResult == SearchSuccess)
704 {
705 /* We don't actually need to do anything! */
707 goto Quickie;
708 }
709
710 /* We need the exclusive KCB lock now */
711 if (!(CmpIsKcbLockedExclusive(Kcb)) &&
713 {
714 /* Acquire exclusive lock */
716 }
717
718 /* Cache lookup failed, so don't try it next time */
719 FirstTry = FALSE;
720
721 /* Now grab the flush lock since the key will be modified */
722 ASSERT(FlusherLocked == FALSE);
723 CmpLockHiveFlusherShared((PCMHIVE)Kcb->KeyHive);
724 FlusherLocked = TRUE;
725 goto DoAgain;
726 }
727 else
728 {
729 /* Get pointer to key cell */
730 Hive = Kcb->KeyHive;
731 Cell = Kcb->KeyCell;
732
733 /* Get the parent */
734 Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
735 ASSERT(Parent);
736 ParentCell = Cell;
737
738 /* Prepare to scan the key node */
739 Count = Parent->ValueList.Count;
740 Found = FALSE;
741 if (Count > 0)
742 {
743 /* Try to find the existing name */
745 &Parent->ValueList,
746 ValueName,
747 &ChildIndex,
748 &CurrentChild);
749 if (!Result)
750 {
751 /* Fail */
753 goto Quickie;
754 }
755
756 /* Check if we found something */
757 if (CurrentChild != HCELL_NIL)
758 {
759 /* Release existing child */
760 if (ChildCell != HCELL_NIL)
761 {
762 HvReleaseCell(Hive, ChildCell);
763 ChildCell = HCELL_NIL;
764 }
765
766 /* Get its value */
767 Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
768 if (!Value)
769 {
770 /* Fail */
772 goto Quickie;
773 }
774
775 /* Remember that we found it */
776 ChildCell = CurrentChild;
777 Found = TRUE;
778 }
779 }
780 else
781 {
782 /* No child list, we'll need to add it */
783 ChildIndex = 0;
784 }
785 }
786
787 /* Should only get here on the second pass */
789
790 /* The KCB must be locked exclusive at this point */
792
793 /* Mark the cell dirty */
794 if (!HvMarkCellDirty(Hive, Cell, FALSE))
795 {
796 /* Not enough log space, fail */
798 goto Quickie;
799 }
800
801 /* Get the storage type */
802 Storage = HvGetCellType(Cell);
803
804 /* Check if this is small data */
805 SmallData = 0;
806 if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
807 {
808 /* Need SEH because user data may be invalid */
810 {
811 /* Copy it */
812 RtlCopyMemory(&SmallData, Data, DataLength);
813 }
815 {
816 /* Return failure code */
818 _SEH2_YIELD(goto Quickie);
819 }
820 _SEH2_END;
821 }
822
823 /* Check if we didn't find a matching key */
824 if (!Found)
825 {
826 /* Call the internal routine */
828 Parent,
829 ValueName,
830 ChildIndex,
831 Type,
832 Data,
834 Storage,
835 SmallData);
836 }
837 else
838 {
839 /* Call the internal routine */
841 CurrentChild,
842 Value,
843 Type,
844 Data,
846 Storage,
847 SmallData);
848 }
849
850 /* Check for success */
851 if (NT_SUCCESS(Status))
852 {
853 /* Check if the maximum value name length changed */
854 ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
855 if (Parent->MaxValueNameLen < ValueName->Length)
856 {
857 /* Set the new values */
858 Parent->MaxValueNameLen = ValueName->Length;
859 Kcb->KcbMaxValueNameLen = ValueName->Length;
860 }
861
862 /* Check if the maximum data length changed */
863 ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
864 if (Parent->MaxValueDataLen < DataLength)
865 {
866 /* Update it */
867 Parent->MaxValueDataLen = DataLength;
868 Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen;
869 }
870
871 /* Save the write time */
872 KeQuerySystemTime(&Parent->LastWriteTime);
873 Kcb->KcbLastWriteTime = Parent->LastWriteTime;
874
875 /* Check if the cell is cached */
876 if ((Found) && (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)))
877 {
878 /* Shouldn't happen */
879 ASSERT(FALSE);
880 }
881 else
882 {
883 /* Cleanup the value cache */
885
886 /* Sanity checks */
887 ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
888 ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
889
890 /* Set the value cache */
891 Kcb->ValueCache.Count = Parent->ValueList.Count;
892 Kcb->ValueCache.ValueList = Parent->ValueList.List;
893 }
894
895 /* Notify registered callbacks */
896 CmpReportNotify(Kcb,
897 Hive,
898 Kcb->KeyCell,
900 }
901
902 /* Release the cells */
903Quickie:
904 if ((ParentCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ParentCell);
905 if ((ChildCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ChildCell);
906
907 /* Release the locks */
908 if (FlusherLocked) CmpUnlockHiveFlusher((PCMHIVE)Hive);
911 return Status;
912}
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:271
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:147
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 2210 of file cmapi.c.

2212{
2213 PHHIVE Hive;
2214 PCMHIVE CmHive;
2215 HCELL_INDEX Cell;
2216
2217 DPRINT("CmUnloadKey(%p, %lx)\n", Kcb, Flags);
2218
2219 /* Get the hive */
2220 Hive = Kcb->KeyHive;
2221 Cell = Kcb->KeyCell;
2222 CmHive = (PCMHIVE)Hive;
2223
2224 /* Fail if the key is not a hive root key */
2225 if (Cell != Hive->BaseBlock->RootCell)
2226 {
2227 DPRINT1("Key is not a hive root key!\n");
2229 }
2230
2231 /* Fail if we try to unload the master hive */
2232 if (CmHive == CmiVolatileHive)
2233 {
2234 DPRINT1("Do not try to unload the master hive!\n");
2236 }
2237
2238 /* Mark this hive as being unloaded */
2240
2241 /* Search for any opened keys in this hive, and take an appropriate action */
2242 if (Kcb->RefCount > 1)
2243 {
2244 if (Flags != REG_FORCE_UNLOAD)
2245 {
2246 if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE) != 0)
2247 {
2248 /* There are open subkeys but we don't force hive unloading, fail */
2249 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2250 return STATUS_CANNOT_DELETE;
2251 }
2252 }
2253 else
2254 {
2255 DPRINT1("CmUnloadKey: Force unloading is HALF-IMPLEMENTED, expect dangling KCBs problems!\n");
2256 if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE) != 0)
2257 {
2258 /* There are open subkeys that we cannot force to unload, fail */
2259 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2260 return STATUS_CANNOT_DELETE;
2261 }
2262 }
2263 }
2264
2265 /* Set the loading flag */
2266 CmHive->HiveIsLoading = TRUE;
2267
2268 /* Flush the hive */
2269 CmFlushKey(Kcb, TRUE);
2270
2271 /* Unlink the hive from the master hive */
2272 if (!CmpUnlinkHiveFromMaster(CmHive, Cell))
2273 {
2274 DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
2275
2276 /* Remove the unloading flag */
2277 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
2278
2279 /* Reset the loading flag */
2280 CmHive->HiveIsLoading = FALSE;
2281
2282 /* Return failure */
2284 }
2285
2286 /* Flush any notifications if we force hive unloading */
2287 if (Flags == REG_FORCE_UNLOAD)
2288 CmpFlushNotifiesOnKeyBodyList(Kcb, TRUE); // Lock is already held
2289
2290 /* Clean up information we have on the subkey */
2291 CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
2292
2293 /* Set the KCB in delete mode and remove it */
2294 Kcb->Delete = TRUE;
2296
2297 if (Flags != REG_FORCE_UNLOAD)
2298 {
2299 /* Release the KCB locks */
2300 CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
2301
2302 /* Release the hive loading lock */
2304 }
2305
2306 /* Release hive lock */
2308
2309 /* Close file handles */
2310 CmpCloseHiveFiles(CmHive);
2311
2312 /* Remove the hive from the hive file list */
2314
2319 /* Destroy the security descriptor cache */
2321
2322 /* Destroy the view list */
2323 CmpDestroyHiveViewList(CmHive);
2324
2325 /* Delete the flusher lock */
2328
2329 /* Delete the view lock */
2331
2332 /* Free the hive storage */
2333 HvFree(Hive);
2334
2335 /* Free the hive */
2336 CmpFree(CmHive, TAG_CM);
2337
2338 return STATUS_SUCCESS;
2339}
#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:2170
NTSTATUS NTAPI CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN ExclusiveLock)
Definition: cmapi.c:1938
ULONG NTAPI CmpEnumerateOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb, IN BOOLEAN RemoveEmptyCacheEntries, IN BOOLEAN DereferenceOpenedEntries)
Definition: cmapi.c:2343
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().