- Implement CmGetSystemControlValues and all related low-level Cm functionality required to select the proper control set and read all the kernel variables during Phase 0 initialization. We can now read time-zone data, version, suite, language IDs and other important kernel variables in the lowest-level boot phase.

- New code uses cmlib from Filip Navara without any modification, and is fully compatible with reading Windows hives as well except XP's "Big value cells" (cells with > 2GB data) which aren't supported.
- Create /config directory where the new Configuration Manager code lies.

svn path=/trunk/; revision=26666
This commit is contained in:
Alex Ionescu 2007-05-09 18:30:21 +00:00
parent 5aaa1671e7
commit 33ea79c7fe
13 changed files with 3312 additions and 14 deletions

View file

@ -1,12 +0,0 @@
#include "ntoskrnl.h"
#include "cm.h"
#include "debug.h"
VOID
NTAPI
CmGetSystemControlValues(IN PVOID SystemHiveData,
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
{
return;
}

View file

@ -0,0 +1,968 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/cm/cm.h
* PURPOSE: Internal header for the Configuration Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
#define _CM_
#include "cmlib.h"
//
// Define this if you want debugging support
//
#define _CM_DEBUG_ 0x00
//
// These define the Debug Masks Supported
//
#define CM_HANDLE_DEBUG 0x01
#define CM_NAMESPACE_DEBUG 0x02
#define CM_SECURITY_DEBUG 0x04
#define CM_REFERENCE_DEBUG 0x08
#define CM_CALLBACK_DEBUG 0x10
//
// Debug/Tracing support
//
#if _CM_DEBUG_
#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
#define CMTRACE DbgPrintEx
#else
#define CMTRACE(x, ...) \
if (x & CmpTraceLevel) DbgPrint(__VA_ARGS__)
#endif
#else
#define CMTRACE(x, ...) DPRINT(__VA_ARGS__)
#endif
//
// Tag for all registry allocations
//
#define TAG_CM \
TAG('C', 'm', ' ', ' ')
//
// Hive operations
//
#define HINIT_CREATE 0
#define HINIT_MEMORY 1
#define HINIT_FILE 2
#define HINIT_MEMORY_INPLACE 3
#define HINIT_FLAT 4
#define HINIT_MAPFILE 5
//
// Hive flags
//
#define HIVE_VOLATILE 1
#define HIVE_NOLAZYFLUSH 2
//
// Hive types
//
#define HFILE_TYPE_PRIMARY 0
#define HFILE_TYPE_ALTERNATE 1
#define HFILE_TYPE_LOG 2
#define HFILE_TYPE_EXTERNAL 3
#define HFILE_TYPE_MAX 4
//
// Hive sizes
//
#define HBLOCK_SIZE 0x1000
#define HSECTOR_SIZE 0x200
#define HSECTOR_COUNT 8
//
// Hive versions
//
#define HSYS_MAJOR 1
#define HSYS_MINOR 3
#define HSYS_WHISTLER_BETA1 4
//
// Cell Masks
//
#define HCELL_NIL 0
#define HCELL_CACHED 1
//
// Key Types
//
#define CM_KEY_INDEX_ROOT 0x6972
#define CM_KEY_INDEX_LEAF 0x696c
#define CM_KEY_FAST_LEAF 0x666c
#define CM_KEY_HASH_LEAF 0x686c
//
// CM_KEY_CONTROL_BLOCK Flags
//
#define CM_KCB_NO_SUBKEY 0x01
#define CM_KCB_SUBKEY_ONE 0x02
#define CM_KCB_SUBKEY_HINT 0x04
#define CM_KCB_SYM_LINK_FOUND 0x08
#define CM_KCB_KEY_NON_EXIST 0x10
#define CM_KCB_NO_DELAY_CLOSE 0x20
#define CM_KCB_INVALID_CACHED_INFO 0x40
#define CM_KEY_READ_ONLY_KEY 0x80
//
// CM_KEY_NODE Signature and Flags
//
#define CM_KEY_NODE_SIGNATURE 0x6B6E
#define CM_LINK_NODE_SIGNATURE 0x6B6C
#define KEY_IS_VOLATILE 0x01
#define KEY_HIVE_EXIT 0x02
#define KEY_HIVE_ENTRY 0x04
#define KEY_NO_DELETE 0x08
#define KEY_SYM_LINK 0x10
#define KEY_COMP_NAME 0x20
#define KEY_PREFEF_HANDLE 0x40
#define KEY_VIRT_MIRRORED 0x80
#define KEY_VIRT_TARGET 0x100
#define KEY_VIRTUAL_STORE 0x200
//
// CM_KEY_VALUE Signature and Flags
//
#define CM_KEY_VALUE_SIGNATURE 0x6b76
#define CM_KEY_VALUE_SMALL 0x4
#define CM_KEY_VALUE_BIG 0x3FD8
#define CM_KEY_VALUE_SPECIAL_SIZE 0x80000000
#define VALUE_COMP_NAME 0x0001
//
// Number of various lists and hashes
//
#define CMP_SECURITY_HASH_LISTS 64
#define CMP_MAX_CALLBACKS 100
//
// Hashing Constants
//
#define CMP_HASH_IRRATIONAL 314159269
#define CMP_HASH_PRIME 1000000007
//
// CmpCreateKcb Flags
//
#define CMP_CREATE_FAKE_KCB 0x1
#define CMP_LOCK_HASHES_FOR_KCB 0x2
//
// Number of items that can fit inside an Allocation Page
//
#define CM_KCBS_PER_PAGE \
PAGE_SIZE / sizeof(CM_KEY_CONTROL_BLOCK)
#define CM_DELAYS_PER_PAGE \
PAGE_SIZE / sizeof(CM_DELAYED_CLOSE_ENTRY)
//
// Key Hash
//
typedef struct _CM_KEY_HASH
{
ULONG ConvKey;
struct _CM_KEY_HASH *NextHash;
PHHIVE KeyHive;
HCELL_INDEX KeyCell;
} CM_KEY_HASH, *PCM_KEY_HASH;
//
// Key Hash Table Entry
//
typedef struct _CM_KEY_HASH_TABLE_ENTRY
{
EX_PUSH_LOCK Lock;
PKTHREAD Owner;
PCM_KEY_HASH Entry;
} CM_KEY_HASH_TABLE_ENTRY, *PCM_KEY_HASH_TABLE_ENTRY;
//
// Name Hash
//
typedef struct _CM_NAME_HASH
{
ULONG ConvKey;
struct _CM_NAME_HASH *NextHash;
USHORT NameLength;
WCHAR Name[ANYSIZE_ARRAY];
} CM_NAME_HASH, *PCM_NAME_HASH;
//
// Name Hash Table Entry
//
typedef struct _CM_NAME_HASH_TABLE_ENTRY
{
EX_PUSH_LOCK Lock;
PCM_NAME_HASH Entry;
} CM_NAME_HASH_TABLE_ENTRY, *PCM_NAME_HASH_TABLE_ENTRY;
//
// Key Security Cache
//
typedef struct _CM_KEY_SECURITY_CACHE
{
HCELL_INDEX Cell;
ULONG ConvKey;
LIST_ENTRY List;
ULONG DescriptorLength;
SECURITY_DESCRIPTOR_RELATIVE Descriptor;
} CM_KEY_SECURITY_CACHE, *PCM_KEY_SECURITY_CACHE;
//
// Key Security Cache Entry
//
typedef struct _CM_KEY_SECURITY_CACHE_ENTRY
{
HCELL_INDEX Cell;
PCM_KEY_SECURITY_CACHE CachedSecurity;
} CM_KEY_SECURITY_CACHE_ENTRY, *PCM_KEY_SECURITY_CACHE_ENTRY;
//
// Cached Child List
//
typedef struct _CACHED_CHILD_LIST
{
ULONG Count;
union
{
ULONG ValueList;
struct _CM_KEY_CONTROL_BLOCK *RealKcb;
};
} CACHED_CHILD_LIST, *PCACHED_CHILD_LIST;
//
// Index Hint Block
//
typedef struct _CM_INDEX_HINT_BLOCK
{
ULONG Count;
ULONG HashKey[ANYSIZE_ARRAY];
} CM_INDEX_HINT_BLOCK, *PCM_INDEX_HINT_BLOCK;
//
// Key Reference
//
typedef struct _CM_KEY_REFERENCE
{
HCELL_INDEX KeyCell;
PHHIVE KeyHive;
} CM_KEY_REFERENCE, *PCM_KEY_REFERENCE;
//
// Key Body
//
typedef struct _CM_KEY_BODY
{
ULONG Type;
struct _CM_KEY_CONTROL_BLOCK *KeyControlBlock;
struct _CM_NOTIFY_BLOCK *NotifyBlock;
HANDLE ProcessID;
ULONG Callers;
PVOID CallerAddress[10];
LIST_ENTRY KeyBodyList;
} CM_KEY_BODY, *PCM_KEY_BODY;
//
// Name Control Block (NCB)
//
typedef struct _CM_NAME_CONTROL_BLOCK
{
BOOLEAN Compressed;
USHORT RefCount;
union
{
CM_NAME_HASH NameHash;
struct
{
ULONG ConvKey;
PCM_KEY_HASH NextHash;
USHORT NameLength;
WCHAR Name[ANYSIZE_ARRAY];
};
};
} CM_NAME_CONTROL_BLOCK, *PCM_NAME_CONTROL_BLOCK;
//
// Key Control Block (KCB)
//
typedef struct _CM_KEY_CONTROL_BLOCK
{
USHORT RefCount;
USHORT Flags;
ULONG ExtFlags:8;
ULONG PrivateAlloc:1;
ULONG Delete:1;
ULONG DelayedCloseIndex:12;
ULONG TotalLevels:10;
union
{
CM_KEY_HASH KeyHash;
struct
{
ULONG ConvKey;
PCM_KEY_HASH NextHash;
PHHIVE KeyHive;
HCELL_INDEX KeyCell;
};
};
struct _CM_KEY_CONTROL_BLOCK *ParentKcb;
PCM_NAME_CONTROL_BLOCK NameBlock;
PCM_KEY_SECURITY_CACHE CachedSecurity;
CACHED_CHILD_LIST ValueCache;
PCM_INDEX_HINT_BLOCK IndexHint;
ULONG HashKey;
ULONG SubKeyCount;
union
{
LIST_ENTRY KeyBodyListHead;
LIST_ENTRY FreeListEntry;
};
PCM_KEY_BODY KeyBodyArray[4];
PVOID DelayCloseEntry;
LARGE_INTEGER KcbLastWriteTime;
USHORT KcbMaxNameLen;
USHORT KcbMaxValueNameLen;
ULONG KcbMaxValueDataLen;
ULONG InDelayClose;
} CM_KEY_CONTROL_BLOCK, *PCM_KEY_CONTROL_BLOCK;
//
// Notify Block
//
typedef struct _CM_NOTIFY_BLOCK
{
LIST_ENTRY HiveList;
LIST_ENTRY PostList;
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
PCM_KEY_BODY KeyBody;
ULONG Filter:29;
ULONG WatchTree:30;
ULONG NotifyPending:31;
} CM_NOTIFY_BLOCK, *PCM_NOTIFY_BLOCK;
//
// Re-map Block
//
typedef struct _CM_CELL_REMAP_BLOCK
{
HCELL_INDEX OldCell;
HCELL_INDEX NewCell;
} CM_CELL_REMAP_BLOCK, *PCM_CELL_REMAP_BLOCK;
//
// Allocation Page
//
typedef struct _CM_ALLOC_PAGE
{
ULONG FreeCount;
ULONG Reserved;
PVOID AllocPage;
} CM_ALLOC_PAGE, *PCM_ALLOC_PAGE;
//
// Delayed Close Entry
//
typedef struct _CM_DELAYED_CLOSE_ENTRY
{
LIST_ENTRY DelayedLRUList;
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
} CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY;
//
// Delayed KCB Dereference Entry
//
typedef struct _CM_DELAY_DEREF_KCB_ITEM
{
LIST_ENTRY ListEntry;
PCM_KEY_CONTROL_BLOCK Kcb;
} CM_DELAY_DEREF_KCB_ITEM, *PCM_DELAY_DEREF_KCB_ITEM;
//
// Use Count Log and Entry
//
typedef struct _CM_USE_COUNT_LOG_ENTRY
{
HCELL_INDEX Cell;
PVOID Stack[7];
} CM_USE_COUNT_LOG_ENTRY, *PCM_USE_COUNT_LOG_ENTRY;
typedef struct _CM_USE_COUNT_LOG
{
USHORT Next;
USHORT Size;
CM_USE_COUNT_LOG_ENTRY Log[32];
} CM_USE_COUNT_LOG, *PCM_USE_COUNT_LOG;
//
// Configuration Manager Hive Structure
//
typedef struct _CMHIVE
{
HHIVE Hive;
HANDLE FileHandles[3];
LIST_ENTRY NotifyList;
LIST_ENTRY HiveList;
EX_PUSH_LOCK HiveLock;
PKTHREAD HiveLockOwner;
PKGUARDED_MUTEX ViewLock;
PKTHREAD ViewLockOwner;
EX_PUSH_LOCK WriterLock;
PKTHREAD WriterLockOwner;
PERESOURCE FlusherLock;
EX_PUSH_LOCK SecurityLock;
PKTHREAD HiveSecurityLockOwner;
LIST_ENTRY LRUViewListHead;
LIST_ENTRY PinViewListHead;
PFILE_OBJECT FileObject;
UNICODE_STRING FileFullPath;
UNICODE_STRING FileUserName;
USHORT MappedViews;
USHORT PinnedViews;
ULONG UseCount;
ULONG SecurityCount;
ULONG SecurityCacheSize;
LONG SecurityHitHint;
PCM_KEY_SECURITY_CACHE_ENTRY SecurityCache;
LIST_ENTRY SecurityHash[CMP_SECURITY_HASH_LISTS];
PKEVENT UnloadEvent;
PCM_KEY_CONTROL_BLOCK RootKcb;
BOOLEAN Frozen;
PWORK_QUEUE_ITEM UnloadWorkItem;
BOOLEAN GrowOnlyMode;
ULONG GrowOffset;
LIST_ENTRY KcbConvertListHead;
LIST_ENTRY KnodeConvertListHead;
PCM_CELL_REMAP_BLOCK CellRemapArray;
CM_USE_COUNT_LOG UseCountLog;
CM_USE_COUNT_LOG LockHiveLog;
ULONG Flags;
LIST_ENTRY TrustClassEntry;
ULONG FlushCount;
BOOLEAN HiveIsLoading;
PKTHREAD CreatorOwner;
} CMHIVE, *PCMHIVE;
#include <pshpack1.h>
typedef struct _CM_VIEW_OF_FILE
{
LIST_ENTRY LRUViewList;
LIST_ENTRY PinViewList;
ULONG FileOffset;
ULONG Size;
PULONG ViewAddress;
PVOID Bcb;
ULONG UseCount;
} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
typedef struct _CHILD_LIST
{
ULONG Count;
HCELL_INDEX List;
} CHILD_LIST, *PCHILD_LIST;
typedef struct _CM_KEY_NODE
{
USHORT Id;
USHORT Flags;
LARGE_INTEGER LastWriteTime;
ULONG Spare;
HCELL_INDEX Parent;
ULONG SubKeyCounts[HvMaxStorageType];
HCELL_INDEX SubKeyLists[HvMaxStorageType];
CHILD_LIST ValueList;
HCELL_INDEX SecurityKeyOffset;
HCELL_INDEX ClassNameOffset;
ULONG MaxNameLen;
ULONG MaxClassLen;
ULONG MaxValueNameLen;
ULONG MaxValueDataLen;
ULONG WorkVar;
USHORT NameLength;
USHORT ClassSize;
WCHAR Name[0];
} CM_KEY_NODE, *PCM_KEY_NODE;
typedef struct _VALUE_LIST_CELL
{
HCELL_INDEX ValueOffset[0];
} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
typedef struct _CM_KEY_VALUE
{
USHORT Signature; // "kv"
USHORT NameLength; // length of Name
ULONG DataLength; // length of datas in the cell pointed by DataOffset
HCELL_INDEX Data;// datas are here if high bit of DataSize is set
ULONG Type;
USHORT Flags;
USHORT Unused1;
WCHAR Name[0]; /* warning : not zero terminated */
} CM_KEY_VALUE, *PCM_KEY_VALUE;
typedef struct _CM_KEY_SECURITY
{
USHORT Signature; // "sk"
USHORT Reserved;
HCELL_INDEX Flink;
HCELL_INDEX Blink;
ULONG ReferenceCount;
ULONG DescriptorLength;
//SECURITY_DESCRIPTOR_RELATIVE Descriptor;
UCHAR Data[0];
} CM_KEY_SECURITY, *PCM_KEY_SECURITY;
#include <poppack.h>
//
// Generic Index Entry
//
typedef struct _CM_INDEX
{
HCELL_INDEX Cell;
union
{
UCHAR NameHint[4];
ULONG HashKey;
};
} CM_INDEX, *PCM_INDEX;
//
// Key Index
//
typedef struct _CM_KEY_INDEX
{
USHORT Signature;
USHORT Count;
HCELL_INDEX List[ANYSIZE_ARRAY];
} CM_KEY_INDEX, *PCM_KEY_INDEX;
//
// Fast/Hash Key Index
//
typedef struct _CM_KEY_FAST_INDEX
{
USHORT Signature;
USHORT Count;
CM_INDEX List[ANYSIZE_ARRAY];
} CM_KEY_FAST_INDEX, *PCM_KEY_FAST_INDEX;
//
// Cell Data
//
typedef struct _CELL_DATA
{
union
{
CM_KEY_NODE KeyNode;
CM_KEY_VALUE KeyValue;
CM_KEY_SECURITY KeySecurity;
CM_KEY_INDEX KeyIndex;
HCELL_INDEX KeyList[ANYSIZE_ARRAY];
WCHAR KeyString[ANYSIZE_ARRAY];
} u;
} CELL_DATA, *PCELL_DATA;
//
// Cached Value Index
//
typedef struct _CM_CACHED_VALUE_INDEX
{
HCELL_INDEX CellIndex;
union
{
CELL_DATA CellData;
ULONG_PTR List[ANYSIZE_ARRAY];
} Data;
} CM_CACHED_VALUE_INDEX, *PCM_CACHED_VALUE_INDEX;
//
// Cached Value
//
typedef struct _CM_CACHED_VALUE
{
USHORT DataCacheType;
USHORT ValueKeySize;
CM_KEY_VALUE KeyValue;
} CM_CACHED_VALUE, *PCM_CACHED_VALUE;
//
// Hive List Entry
//
typedef struct _HIVE_LIST_ENTRY
{
PWCHAR FileName;
PWCHAR BaseName;
PWCHAR RegRootName;
PCMHIVE CmHive;
ULONG HHiveFlags;
ULONG CmHiveFlags;
PCMHIVE CmHive2;
BOOLEAN ThreadFinished;
BOOLEAN ThreadStarted;
BOOLEAN Allocate;
BOOLEAN WinPERequired;
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
//
// Parse context for Key Object
//
typedef struct _CM_PARSE_CONTEXT
{
ULONG TitleIndex;
UNICODE_STRING Class;
ULONG CreateOptions;
ULONG Disposition;
CM_KEY_REFERENCE ChildHive;
BOOLEAN CreateLink;
BOOLEAN Flag2;
HANDLE PredefinedHandle;
ULONG PostActions;
} CM_PARSE_CONTEXT, *PCM_PARSE_CONTEXT;
//
// System Control Vector
//
typedef struct _CM_SYSTEM_CONTROL_VECTOR
{
PWCHAR KeyPath;
PWCHAR ValueName;
PVOID Buffer;
PULONG BufferLength;
PULONG Type;
} CM_SYSTEM_CONTROL_VECTOR, *PCM_SYSTEM_CONTROL_VECTOR;
//
// Mapped View Hive Functions
//
VOID
NTAPI
CmpInitHiveViewList(
IN PCMHIVE Hive
);
//
// Security Cache Functions
//
VOID
NTAPI
CmpInitSecurityCache(
IN PCMHIVE Hive
);
//
// Registry Validation Functions
//
BOOLEAN
NTAPI
CmCheckRegistry(
IN PCMHIVE Hive,
IN BOOLEAN CleanFlag
);
//
// Notification Routines
//
VOID
CmpReportNotify(
IN PCM_KEY_CONTROL_BLOCK Kcb,
IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN ULONG Filter
);
//
// KCB Cache/Delay Routines
//
VOID
NTAPI
CmpInitializeCache(
VOID
);
VOID
NTAPI
CmpInitializeCmAllocations(
VOID
);
VOID
NTAPI
CmpInitializeKcbDelayedDeref(
VOID
);
//
// Key Object Routines
//
VOID
NTAPI
CmpCloseKeyObject(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount
);
VOID
NTAPI
CmpDeleteKeyObject(
IN PVOID Object
);
NTSTATUS
NTAPI
CmpParseKey(
IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object
);
NTSTATUS
NTAPI
CmpSecurityMethod(
IN PVOID Object,
IN SECURITY_OPERATION_CODE OperationType,
IN PSECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN OUT PULONG CapturedLength,
IN OUT PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
IN POOL_TYPE PoolType,
IN PGENERIC_MAPPING GenericMapping
);
NTSTATUS
NTAPI
CmpQueryKeyName(
IN PVOID Object,
IN BOOLEAN HasObjectName,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength,
IN KPROCESSOR_MODE AccessMode
);
//
// Hive Routines
//
NTSTATUS
NTAPI
CmpInitializeHive(
OUT PCMHIVE *CmHive,
IN ULONG Operation,
IN ULONG Flags,
IN ULONG FileType,
IN PVOID HiveData,
IN HANDLE Primary,
IN HANDLE Alternate,
IN HANDLE Log,
IN HANDLE External,
IN PUNICODE_STRING FileName
);
PSECURITY_DESCRIPTOR
NTAPI
CmpHiveRootSecurityDescriptor(
VOID
);
NTSTATUS
NTAPI
CmpLinkHiveToMaster(
IN PUNICODE_STRING LinkName,
IN HANDLE RootDirectory,
IN PCMHIVE CmHive,
IN BOOLEAN Allocate,
IN PSECURITY_DESCRIPTOR SecurityDescriptor
);
//
// Registry Utility Functions
//
BOOLEAN
NTAPI
CmpTestRegistryLockExclusive(
VOID
);
VOID
NTAPI
CmpLockRegistryExclusive(
VOID
);
VOID
NTAPI
CmpUnlockRegistry(
VOID
);
PVOID
NTAPI
CmpAllocateDelayItem(
VOID
);
VOID
NTAPI
CmpFreeDelayItem(
PVOID Entry
);
//
// KCB Functions
//
PCM_KEY_CONTROL_BLOCK
NTAPI
CmpCreateKcb(
IN PHHIVE Hive,
IN HCELL_INDEX Index,
IN PCM_KEY_NODE Node,
IN PCM_KEY_CONTROL_BLOCK Parent,
IN ULONG Flags,
IN PUNICODE_STRING KeyName
);
VOID
NTAPI
CmpDereferenceKcbWithLock(
IN PCM_KEY_CONTROL_BLOCK Kcb,
IN BOOLEAN LockHeldExclusively
);
//
// Name Functions
//
LONG
NTAPI
CmpCompareCompressedName(
IN PUNICODE_STRING SearchName,
IN PWCHAR CompressedName,
IN ULONG NameLength
);
USHORT
NTAPI
CmpNameSize(
IN PHHIVE Hive,
IN PUNICODE_STRING Name
);
USHORT
NTAPI
CmpCopyName(
IN PHHIVE Hive,
IN PWCHAR Destination,
IN PUNICODE_STRING Source
);
BOOLEAN
NTAPI
CmpFindNameInList(
IN PHHIVE Hive,
IN PCHILD_LIST ChildList,
IN PUNICODE_STRING Name,
IN PULONG ChildIndex,
IN PHCELL_INDEX CellIndex
);
//
// Parse Routines
//
BOOLEAN
NTAPI
CmpGetNextName(
IN OUT PUNICODE_STRING RemainingName,
OUT PUNICODE_STRING NextName,
OUT PBOOLEAN LastName
);
//
// Flush Routines
//
BOOLEAN
NTAPI
CmpFlushEntireRegistry(
IN BOOLEAN ForceFlush
);
//
// Cell Index Routines
//
HCELL_INDEX
NTAPI
CmpFindSubKeyByName(
IN PHHIVE Hive,
IN PCM_KEY_NODE Parent,
IN PUNICODE_STRING SearchName
);
//
// Cell Value Routines
//
HCELL_INDEX
NTAPI
CmpFindValueByName(
IN PHHIVE Hive,
IN PCM_KEY_NODE KeyNode,
IN PUNICODE_STRING Name
);
PCELL_DATA
NTAPI
CmpValueToData(
IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
OUT PULONG Length
);
//
// Boot Routines
//
HCELL_INDEX
NTAPI
CmpFindControlSet(
IN PHHIVE SystemHive,
IN HCELL_INDEX RootCell,
IN PUNICODE_STRING SelectKeyName,
OUT PBOOLEAN AutoSelect
);
//
// Global variables accessible from all of Cm
//
extern BOOLEAN CmpSpecialBootCondition;
extern BOOLEAN CmpFlushOnLockRelease;
extern EX_PUSH_LOCK CmpHiveListHeadLock;
extern LIST_ENTRY CmpHiveListHead;
extern POBJECT_TYPE CmpKeyObjectType;
extern ERESOURCE CmpRegistryLock;
extern PCM_KEY_HASH_TABLE_ENTRY *CmpCacheTable;
extern PCM_NAME_HASH_TABLE_ENTRY *CmpNameCacheTable;
extern KGUARDED_MUTEX CmpDelayedCloseTableLock;
extern CMHIVE CmControlHive;
extern WCHAR CmDefaultLanguageId[];
extern ULONG CmDefaultLanguageIdLength;
extern ULONG CmDefaultLanguageIdType;
extern WCHAR CmInstallUILanguageId[];
extern ULONG CmInstallUILanguageIdLength;
extern ULONG CmInstallUILanguageIdType;
extern LANGID PsInstallUILanguageId;
extern LANGID PsDefaultUILanguageId;
extern CM_SYSTEM_CONTROL_VECTOR CmControlVector[];
//
// Inlined functions
//
#include "cm_x.h"

View file

@ -0,0 +1,143 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/cm/cm_x.h
* PURPOSE: Inlined Functions for the Configuration Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
//
// Returns whether or not this is a small valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueSmall(OUT PULONG RealLength,
IN ULONG Length)
{
/* Check if the length has the special size value */
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
{
/* It does, so this is a small key: return the real length */
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
return TRUE;
}
/* This is not a small key, return the length we read */
*RealLength = Length;
return FALSE;
}
//
// Returns whether or not this is a big valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueBig(IN PHHIVE Hive,
IN ULONG Length)
{
/* Check if the hive is XP Beta 1 or newer */
if (Hive->Version >= HSYS_WHISTLER_BETA1)
{
/* Check if the key length is valid for a big value key */
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
{
/* Yes, this value is big */
return TRUE;
}
}
/* Not a big value key */
return FALSE;
}
//
// Returns the hashkey corresponding to a convkey
//
#define GET_HASH_KEY(ConvKey) \
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
//
// Returns the index into the hash table, or the entry itself
//
#define GET_HASH_INDEX(ConvKey) \
GET_HASH_KEY(ConvKey) % CmpHashTableSize
#define GET_HASH_ENTRY(Table, ConvKey) \
(*Table[GET_HASH_INDEX(ConvKey)])
//
// Returns whether or not the cell is cached
//
#define CMP_IS_CELL_CACHED(c) \
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
//
// Return data from a cached cell
//
#define CMP_GET_CACHED_CELL(c) \
(ULONG_PTR)((c) & ~HCELL_CACHED)
#define CMP_GET_CACHED_DATA(c) \
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
#define CMP_GET_CACHED_INDEX(c) \
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
#define CMP_GET_CACHED_VALUE(c) \
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
//
// Makes sure that the registry is locked
//
#define CMP_ASSERT_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLock() == TRUE))
//
// Makes sure that the registry is exclusively locked
//
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLockExclusive() == TRUE))
//
// Checks if a KCB is exclusively locked
//
#define CmpIsKcbLockedExclusive(k) \
(GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner == KeGetCurrentThread())
//
// Exclusively acquires a KCB
//
#define CmpAcquireKcbLockExclusive(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner = KeGetCurrentThread(); \
}
//
// Releases an exlusively or shared acquired KCB
//
#define CmpReleaseKcbLock(k) \
{ \
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Exclusively acquires an NCB
//
#define CmpAcquireNcbLockExclusive(n) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
(n)->ConvKey).Lock); \
}
//
// Releases an exlusively or shared acquired NCB
//
#define CmpReleaseNcbLock(k) \
{ \
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)->ConvKey).Lock); \
}

View file

@ -0,0 +1,127 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmboot.c
* PURPOSE: Configuration Manager - Boot Initialization
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
HCELL_INDEX
NTAPI
CmpFindControlSet(IN PHHIVE SystemHive,
IN HCELL_INDEX RootCell,
IN PUNICODE_STRING SelectKeyName,
OUT PBOOLEAN AutoSelect)
{
UNICODE_STRING KeyName;
PCM_KEY_NODE Node;
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
HCELL_INDEX CurrentValueCell;
PCM_KEY_VALUE KeyValue;
ULONG Length;
PULONG ControlSetId;
ANSI_STRING ControlSetAnsiName;
CHAR Buffer[128];
WCHAR WideBuffer[128];
NTSTATUS Status;
PULONG CurrentData;
/* Sanity check */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Get the Select subkey */
RtlInitUnicodeString(&KeyName, L"select");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (SelectCell == HCELL_NIL) return SelectCell;
/* Get AutoSelect value */
RtlInitUnicodeString(&KeyName, L"AutoSelect");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
if (AutoSelectCell == HCELL_NIL)
{
/* Assume TRUE if the value is missing. */
*AutoSelect = TRUE;
}
else
{
/* Read the value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
if (KeyValue == NULL) return HCELL_NIL;
/* Convert it to a boolean */
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
}
/* Now find the control set being looked up */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
/* Read the value (corresponding to the CCS ID) */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
/* Now build an Ansi String for the CCS's Name */
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
ControlSetAnsiName.Buffer = Buffer;
/* And convert it to Unicode... */
KeyName.MaximumLength = 256;
KeyName.Buffer = WideBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&ControlSetAnsiName,
FALSE);
if (!NT_SUCCESS(Status)) return HCELL_NIL;
/* Now open it */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
/* Get the value of the "Current" CCS */
RtlInitUnicodeString(&KeyName, L"Current");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
/* Make sure it exists */
if (CurrentValueCell != HCELL_NIL)
{
/* Get the current value and make sure its a ULONG */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type == REG_DWORD)
{
/* Get the data and update it */
CurrentData = (PULONG)CmpValueToData(SystemHive,
KeyValue,
&Length);
if (!CurrentData) return HCELL_NIL;
*CurrentData = *ControlSetId;
}
}
/* Return the CCS Cell */
return ControlSetCell;
}

View file

@ -0,0 +1,262 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmcontrl.c
* PURPOSE: Configuration Manager - Control Set Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
LANGID
NTAPI
CmpConvertLangId(IN LPWSTR Name,
IN ULONG NameLength)
{
ULONG i;
WCHAR p;
LANGID LangId = 0;
ULONG IdCode;
/* Convert the length in chars and loop */
NameLength = NameLength / sizeof(WCHAR);
for (i = 0; i < NameLength; i++)
{
/* Get the character */
p = Name[i];
/* Handle each case */
if ((p >= L'0') && (p <= L'9'))
{
/* Handle digits*/
IdCode = p - L'0';
}
else if ((p >= L'A') && (p <= L'F'))
{
/* Handle upper-case letters */
IdCode = p - L'A' + 10;
}
else if ((p >= L'a') && (p <= L'f'))
{
/* Handle lower-case letters */
IdCode = p - L'a' + 10;
}
else
{
/* Unhandled case, return what we have till now */
break;
}
/* If the ID Code is >= 16, then we're done */
if (IdCode >= 16) break;
/* Build the Language ID */
LangId = (LangId << 4) | (LANGID)IdCode;
}
/* Return the Language ID */
return LangId;
}
HCELL_INDEX
NTAPI
CmpWalkPath(IN PHHIVE SystemHive,
IN HCELL_INDEX ParentCell,
IN LPWSTR Path)
{
UNICODE_STRING UnicodePath, NextName;
BOOLEAN LastName;
HCELL_INDEX CurrentCell = ParentCell;
PCM_KEY_NODE Node;
/* We shouldn't have a release routine at this point */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Initialize the Unicode path and start looping */
RtlInitUnicodeString(&UnicodePath, Path);
while (TRUE)
{
/* Get the next name */
CmpGetNextName(&UnicodePath, &NextName, &LastName);
if (!NextName.Length) return CurrentCell;
/* Get the subkey */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
if (!Node) return HCELL_NIL;
CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
if (CurrentCell == HCELL_NIL) return CurrentCell;
}
}
VOID
NTAPI
CmGetSystemControlValues(IN PVOID SystemHiveData,
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
{
PHHIVE SystemHive = (PHHIVE)&CmControlHive;
NTSTATUS Status;
HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
ULONG Length, DataSize;
PCM_KEY_NODE Node;
PCM_KEY_VALUE ValueData;
UNICODE_STRING KeyName;
BOOLEAN Auto, IsSmallKey;
PVOID Buffer;
/* Initialize the Hive View List and the security cache */
RtlZeroMemory(SystemHive, sizeof(SystemHive));
CmpInitHiveViewList((PCMHIVE)SystemHive);
CmpInitSecurityCache((PCMHIVE)SystemHive);
/* Initialize the Hive */
Status = HvInitialize(SystemHive,
HINIT_MEMORY_INPLACE, /* FIXME: Should be flat */
HIVE_VOLATILE,
HFILE_TYPE_PRIMARY,
(ULONG_PTR)SystemHiveData,
1,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
/* Sanity check, flat hives don't have release routines */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* FIXME: Prepare it */
CmPrepareHive(SystemHive);
/* Set the Root Cell */
RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
/* Find the current control set */
RtlInitUnicodeString(&KeyName, L"current");
BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
/* Find the control subkey */
RtlInitUnicodeString(&KeyName, L"control");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
/* Loop each key */
while (ControlVector->KeyPath)
{
/* Assume failure */
Length = -1;
/* Get the cell for this key */
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
if (KeyCell != HCELL_NIL)
{
/* Now get the cell for the value */
RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
if (ValueCell != HCELL_NIL)
{
/* Check if there's any data */
if (!ControlVector->BufferLength)
{
/* No, the buffer will only be large enough for a ULONG */
DataSize = sizeof(ULONG);
}
else
{
/* Yes, save the data size */
DataSize = *ControlVector->BufferLength;
}
/* Get the actual data */
ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
/* Check if this is a small key */
IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
/* If the length is bigger then our buffer, normalize it */
if (DataSize < Length) Length = DataSize;
/* Make sure we have some data */
if (Length > 0)
{
/* Check if this was a small key */
if (IsSmallKey)
{
/* The buffer is directly safe to read */
Buffer = (PVOID)(&(ValueData->Data));
}
else
{
/* Use the longer path */
Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
}
/* Sanity check if this is a small key */
ASSERT((IsSmallKey ?
(Length <= CM_KEY_VALUE_SMALL) : TRUE));
/* Copy the data in the buffer */
RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
}
/* Check if we should return the data type */
if (ControlVector->Type)
{
/* Return the type that we read */
*ControlVector->Type = ValueData->Type;
}
}
}
/* Return the size that we read */
if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
/* Go to the next entry */
ControlVector++;
}
/* Check if the ID is in the registry */
if (CmDefaultLanguageIdType == REG_SZ)
{
/* Read it */
PsDefaultSystemLocaleId =
(LCID)CmpConvertLangId(CmDefaultLanguageId,
CmDefaultLanguageIdLength);
}
else
{
/* Use EN_US by default */
PsDefaultSystemLocaleId = 0x409;
}
/* Check if the ID Is in the registry */
if (CmInstallUILanguageIdType == REG_SZ)
{
/* Read it */
PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
CmInstallUILanguageIdLength);
}
else
{
/* Otherwise, use the default */
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
}
/* Set the defaults for the Thread UI */
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
PsDefaultUILanguageId = PsInstallUILanguageId;
}

View file

@ -0,0 +1,718 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmdata.c
* PURPOSE: Configuration Manager - Global Configuration Data
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
ULONG DummyData;
ULONG CmNtGlobalFlag;
ULONG CmNtCSDVersion;
WCHAR CmDefaultLanguageId[12];
ULONG CmDefaultLanguageIdLength = sizeof(CmDefaultLanguageId);
ULONG CmDefaultLanguageIdType;
WCHAR CmInstallUILanguageId[12];
ULONG CmInstallUILanguageIdLength = sizeof(CmInstallUILanguageId);
ULONG CmInstallUILanguageIdType;
WCHAR CmSuiteBuffer[128];
ULONG CmSuiteBufferLength = sizeof(CmSuiteBuffer);
ULONG CmSuiteBufferType;
CMHIVE CmControlHive;
CM_SYSTEM_CONTROL_VECTOR CmControlVector[] =
{
{
L"Session Manager",
L"ProtectionMode",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"ObjectSecurityMode",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"LUIDDeviceMapsDisabled",
&DummyData,
NULL,
NULL
},
{
L"LSA",
L"AuditBaseDirectories",
&DummyData,
NULL,
NULL
},
{
L"LSA",
L"AuditBaseObjects",
&DummyData,
NULL,
NULL
},
{
L"LSA\\audit",
L"ProcessAccessesToAudit",
&DummyData,
NULL,
NULL
},
{
L"TimeZoneInformation",
L"ActiveTimeBias",
&DummyData,
NULL,
NULL
},
{
L"TimeZoneInformation",
L"Bias",
&DummyData,
NULL,
NULL
},
{
L"TimeZoneInformation",
L"RealTimeIsUniversal",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"GlobalFlag",
&CmNtGlobalFlag,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PagedPoolQuota",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"NonPagedPoolQuota",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PagingFileQuota",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"AllocationPreference",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"DynamicMemory",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"Mirroring",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"Mirroring",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SystemViewSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SessionViewSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SessionImageSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SessionPoolSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PoolUsageMaximum",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"MapAllocationFragment",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PagedPoolSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"NonPagedPoolSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"NonPagedPoolMaximumPercent",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"LargeSystemCache",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"LargeStackSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SystemPages",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"LowMemoryThreshold",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"HighMemoryThreshold",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"DisablePagingExecutive",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"ModifiedPageLife",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SecondLevelDataCache",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"ClearPageFileAtShutdown",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PoolTagSmallTableSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PoolTagBigTableSize",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PoolTag",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"PoolTagOverruns",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"SnapUnloads",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"ProtectNonPagedPool",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"TrackLockedPages",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"TrackPtes",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"VerifyDrivers",
&DummyData,
&DummyData,
&DummyData
},
{
L"Session Manager\\Memory Management",
L"VerifyDriverLevel",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"VerifyMode",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"LargePageMinimum",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"EnforceWriteProtection",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"MakeLowMemory",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Memory Management",
L"WriteWatch",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Executive",
L"AdditionalCriticalWorkerThreads",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Executive",
L"AdditionalDelayedWorkerThreads",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Executive",
L"PriorityQuantumMatrix",
&DummyData,
&DummyData,
NULL
},
{
L"Session Manager\\Kernel",
L"DpcQueueDepth",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Kernel",
L"MinimumDpcRate",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Kernel",
L"AdjustDpcThreshold",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Kernel",
L"IdealDpcRate",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\I/O System",
L"CountOperations",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\I/O System",
L"LargeIrpStackLocations",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\I/O System",
L"IoVerifierLevel",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"ResourceTimeoutCount",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"CriticalSectionTimeout",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"HeapSegmentReserve",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"HeapSegmentCommit",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"HeapDeCommitTotalFreeThreshold",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"HeapDeCommitFreeBlockThreshold",
&DummyData,
NULL,
NULL
},
{
L"ProductOptions",
L"ProductType",
&DummyData,
NULL,
NULL
},
{
L"Terminal Server",
L"TSEnabled",
&DummyData,
NULL,
NULL
},
{
L"Terminal Server",
L"TSAppCompat",
&DummyData,
NULL,
NULL
},
{
L"ProductOptions",
L"ProductSuite",
CmSuiteBuffer,
&CmSuiteBufferLength,
&CmSuiteBufferType
},
{
L"Windows",
L"CSDVersion",
&CmNtCSDVersion,
NULL,
NULL
},
{
L"Nls\\Language",
L"Default",
CmDefaultLanguageId,
&CmDefaultLanguageIdLength,
&CmDefaultLanguageIdType
},
{
L"Nls\\Language",
L"InstallLanguage",
CmInstallUILanguageId,
&CmInstallUILanguageIdLength,
&CmInstallUILanguageIdType
},
{
L"\0\0",
L"RegistrySizeLimit",
&DummyData,
&DummyData,
&DummyData
},
{
L"Session Manager",
L"ForceNpxEmulation",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"PowerPolicySimulate",
&DummyData,
NULL,
NULL
},
{
L"Session Manager\\Executive",
L"MaxTimeSeparationBeforeCorrect",
&DummyData,
NULL,
NULL
},
{
L"Windows",
L"ShutdownTime",
&DummyData,
&DummyData,
NULL
},
{
L"PriorityControl",
L"Win32PrioritySeparation",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"EnableTimerWatchdog",
&DummyData,
NULL,
NULL
},
{
L"Session Manager",
L"Debugger Retries",
&DummyData,
NULL,
NULL
},
{
L"WMI",
L"MaxEventSize",
&DummyData,
NULL,
NULL
},
{
L"WMI\\Trace",
L"UsePerformanceClock",
&DummyData,
NULL,
NULL
},
{
L"WMI\\Trace",
L"TraceAlignment",
&DummyData,
NULL,
NULL
},
{
NULL,
NULL,
NULL,
NULL,
NULL
}
};

View file

@ -0,0 +1,646 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmindex.c
* PURPOSE: Configuration Manager - Cell Indexes
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
LONG
NTAPI
CmpDoCompareKeyName(IN PHHIVE Hive,
IN PUNICODE_STRING SearchName,
IN HCELL_INDEX Cell)
{
PCM_KEY_NODE Node;
UNICODE_STRING KeyName;
LONG Result;
/* Get the node */
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
if (!Node) return 2;
/* Check if it's compressed */
if (Node->Flags & KEY_COMP_NAME)
{
/* Compare compressed names */
Result = CmpCompareCompressedName(SearchName,
Node->Name,
Node->NameLength);
}
else
{
/* Compare the Unicode name directly */
KeyName.Buffer = Node->Name;
KeyName.Length = Node->NameLength;
KeyName.MaximumLength = KeyName.Length;
Result = RtlCompareUnicodeString(SearchName, &KeyName, TRUE);
}
/* Release the cell and return the normalized result */
HvReleaseCell(Hive, Cell);
return (Result == 0) ? Result : ((Result > 0) ? 1 : -1);
}
LONG
NTAPI
CmpCompareInIndex(IN PHHIVE Hive,
IN PUNICODE_STRING SearchName,
IN ULONG Count,
IN PCM_KEY_INDEX Index,
IN PHCELL_INDEX SubKey)
{
PCM_KEY_FAST_INDEX FastIndex;
PCM_INDEX FastEntry;
LONG Result;
ULONG i;
ULONG ActualNameLength = 4, CompareLength, NameLength;
WCHAR p, pp;
/* Assume failure */
*SubKey = HCELL_NIL;
/* Check if we are a fast or hashed leaf */
if ((Index->Signature == CM_KEY_FAST_LEAF) ||
(Index->Signature == CM_KEY_HASH_LEAF))
{
/* Get the Fast/Hash Index */
FastIndex = (PCM_KEY_FAST_INDEX)Index;
FastEntry = &FastIndex->List[Count];
/* Check if we are a hash leaf, in which case we skip all this */
if (Index->Signature == CM_KEY_FAST_LEAF)
{
/* Find out just how much of the name is there */
for (i = 0; i < 4; i++)
{
/* Check if this entry is empty */
if (!FastEntry->NameHint[i])
{
/* Only this much! */
ActualNameLength = i;
break;
}
}
/* How large is the name and how many characters to compare */
NameLength = SearchName->Length / sizeof(WCHAR);
CompareLength = min(NameLength, ActualNameLength);
/* Loop all the chars we'll test */
for (i = 0; i < CompareLength; i++)
{
/* Get one char from each buffer */
p = SearchName->Buffer[i];
pp = FastEntry->NameHint[i];
/* See if they match and return result if they don't */
Result = (LONG)RtlUpcaseUnicodeChar(p) -
(LONG)RtlUpcaseUnicodeChar(pp);
if (Result) return (Result > 0) ? 1 : -1;
}
}
/* If we got here then we have to do a full compare */
Result = CmpDoCompareKeyName(Hive, SearchName, FastEntry->Cell);
if (Result == 2) return Result;
if (!Result) *SubKey = FastEntry->Cell;
}
else
{
/* We aren't, so do a name compare and return the subkey found */
Result = CmpDoCompareKeyName(Hive, SearchName, Index->List[Count]);
if (Result == 2) return Result;
if (!Result) *SubKey = Index->List[Count];
}
/* Return the comparison result */
return Result;
}
ULONG
NTAPI
CmpFindSubKeyInRoot(IN PHHIVE Hive,
IN PCM_KEY_INDEX Index,
IN PUNICODE_STRING SearchName,
IN PHCELL_INDEX SubKey)
{
ULONG High, Low = 0, i, ReturnIndex;
HCELL_INDEX LeafCell;
PCM_KEY_INDEX Leaf;
LONG Result;
/* Verify Index for validity */
ASSERTMSG("We don't do a linear search yet!\n", FALSE);
ASSERT(Index->Count != 0);
ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
/* Set high limit and loop */
High = Index->Count - 1;
while (TRUE)
{
/* Choose next entry */
i = ((High - Low) / 2) + Low;
/* Get the leaf cell and then the leaf itself */
LeafCell = Index->List[i];
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
if (Leaf)
{
/* Make sure the leaf is valid */
ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
(Leaf->Signature == CM_KEY_FAST_LEAF) ||
(Leaf->Signature == CM_KEY_HASH_LEAF));
ASSERT(Leaf->Count != 0);
/* Do the compare */
Result = CmpCompareInIndex(Hive,
SearchName,
Leaf->Count - 1,
Leaf,
SubKey);
if (Result == 2) goto Big;
/* Check if we found the leaf */
if (!Result)
{
/* We found the leaf */
*SubKey = LeafCell;
ReturnIndex = i;
goto Return;
}
/* Check for negative result */
if (Result < 0)
{
/* If we got here, we should be at -1 */
ASSERT(Result == -1);
/* Do another lookup, since we might still be in the right leaf */
Result = CmpCompareInIndex(Hive,
SearchName,
0,
Leaf,
SubKey);
if (Result == 2) goto Big;
/* Check if it's not below */
if (Result >= 0)
{
/*
* If the name was first below, and now it is above,
* then this means that it is somewhere in this leaf.
* Make sure we didn't get some weird result
*/
ASSERT((Result == 1) || (Result == 0));
/* Return it */
*SubKey = LeafCell;
ReturnIndex = Low;
goto Return;
}
/* Update the limit to this index, since we know it's not higher. */
High = i;
}
else
{
/* Update the base to this index, since we know it's not lower. */
Low = i;
}
}
else
{
Big:
/* This was some sort of special key */
ReturnIndex = 0x80000000;
goto ReturnFailure;
}
/* Check if there is only one entry left */
if ((High - Low) <= 1) break;
/* Release the leaf cell */
HvReleaseCell(Hive, LeafCell);
}
/* Make sure we got here for the right reasons */
ASSERT((High - Low == 1) || (High == Low));
/* Get the leaf cell and the leaf */
LeafCell = Index->List[Low];
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
if (!Leaf) goto Big;
/* Do the compare */
Result = CmpCompareInIndex(Hive,
SearchName,
Leaf->Count-1,
Leaf,
SubKey);
if (Result == 2) goto Big;
/* Check if we found it */
if (!Result)
{
/* We got lucky...return it */
*SubKey = LeafCell;
ReturnIndex = Low;
goto Return;
}
/* It's below, so could still be in this leaf */
if (Result < 0)
{
/* Make sure we're -1 */
ASSERT(Result == -1);
/* Do a search from the bottom */
Result = CmpCompareInIndex(Hive, SearchName, 0, Leaf, SubKey);
if (Result == 2) goto Big;
/*
* Check if it's above, which means that it's within the ranges of our
* leaf (since we were below before).
*/
if (Result >= 0)
{
/* Sanity check */
ASSERT((Result == 1) || (Result == 0));
/* Yep, so we're in the right leaf; return it. */
*SubKey = LeafCell;
ReturnIndex = Low;
goto Return;
}
/* It's still below us, so fail */
ReturnIndex = Low;
goto ReturnFailure;
}
/* Release the leaf cell */
HvReleaseCell(Hive, LeafCell);
/* Well the low didn't work too well, so try the high. */
LeafCell = Index->List[High];
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
if (!Leaf) goto Big;
/* Do the compare */
Result = CmpCompareInIndex(Hive,
SearchName,
Leaf->Count - 1,
Leaf,
SubKey);
if (Result == 2) goto Big;
/* Check if we found it */
if (Result == 0)
{
/* We got lucky... return it */
*SubKey = LeafCell;
ReturnIndex = High;
goto Return;
}
/* Check if we are too high */
if (Result < 0)
{
/* Make sure we're -1 */
ASSERT(Result == -1);
/*
* Once again... since we were first too low and now too high, then
* this means we are within the range of this leaf... return it.
*/
*SubKey = LeafCell;
ReturnIndex = High;
goto Return;
}
/* If we got here, then we are too low, again. */
ReturnIndex = High;
/* Failure path */
ReturnFailure:
*SubKey = HCELL_NIL;
/* Return path...check if we have a leaf to free */
Return:
if (Leaf) HvReleaseCell(Hive, LeafCell);
/* Return the index */
return ReturnIndex;
}
ULONG
NTAPI
CmpFindSubKeyInLeaf(IN PHHIVE Hive,
IN PCM_KEY_INDEX Index,
IN PUNICODE_STRING SearchName,
IN PHCELL_INDEX SubKey)
{
ULONG High, Low = 0, i;
LONG Result;
/* Verify Index for validity */
ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
(Index->Signature == CM_KEY_FAST_LEAF) ||
(Index->Signature == CM_KEY_HASH_LEAF));
/* Get the upper bound and middle entry */
High = Index->Count - 1;
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
i = High / 2;
#else
i = 0;
#endif
/* Check if we don't actually have any entries */
if (!Index->Count)
{
/* Return failure */
*SubKey = HCELL_NIL;
return 0;
}
/* Start compare loop */
while (TRUE)
{
/* Do the actual comparison and check the result */
Result = CmpCompareInIndex(Hive, SearchName, i, Index, SubKey);
if (Result == 2)
{
/* Fail with special value */
*SubKey = HCELL_NIL;
return 0x80000000;
}
/* Check if we got lucky and found it */
if (!Result) return i;
/* Check if the result is below us */
if (Result < 0)
{
/* Set the new bound; it can't be higher then where we are now. */
ASSERT(Result == -1);
High = i;
}
else
{
/* Set the new bound... it can't be lower then where we are now. */
ASSERT(Result == 1);
Low = i;
}
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
/* Check if this is the last entry, if so, break out and handle it */
if ((High - Low) <= 1) break;
/* Set the new index */
i = ((High - Low) / 2) + Low;
#else
if (++i > High)
{
/* Return failure */
*SubKey = HCELL_NIL;
return 0;
}
#endif
}
/*
* If we get here, High - Low = 1 or High == Low
* Simply look first at Low, then at High
*/
Result = CmpCompareInIndex(Hive, SearchName, Low, Index, SubKey);
if (Result == 2)
{
/* Fail with special value */
*SubKey = HCELL_NIL;
return 0x80000000;
}
/* Check if we got lucky and found it */
if (!Result) return Low;
/* Check if the result is below us */
if (Result < 0)
{
/* Return the low entry */
ASSERT(Result == -1);
return Low;
}
/*
* If we got here, then just check the high and return it no matter what
* the result is (since we're a leaf, it has to be near there anyway).
*/
Result = CmpCompareInIndex(Hive, SearchName, High, Index, SubKey);
if (Result == 2)
{
/* Fail with special value */
*SubKey = HCELL_NIL;
return 0x80000000;
}
/* Return the high */
return High;
}
ULONG
NTAPI
CmpComputeHashKey(IN ULONG Hash,
IN PUNICODE_STRING Name,
IN BOOLEAN AllowSeparators)
{
LPWSTR Cp;
ULONG Value, i;
/* Make some sanity checks on our parameters */
ASSERT((Name->Length == 0) ||
(AllowSeparators) ||
(Name->Buffer[0] != OBJ_NAME_PATH_SEPARATOR));
/* If the name is empty, there is nothing to hash! */
if (!Name->Length) return Hash;
/* Set the buffer and loop every character */
Cp = Name->Buffer;
for (i = 0; i < Name->Length; i += sizeof(WCHAR), Cp++)
{
/* Make sure we don't have a separator when we shouldn't */
ASSERT(AllowSeparators || (*Cp != OBJ_NAME_PATH_SEPARATOR));
/* Check what kind of char we have */
if (*Cp >= L'a')
{
/* In the lower case region... is it truly lower case? */
if (*Cp < L'z')
{
/* Yes! Calculate it ourselves! */
Value = *Cp - L'a' + L'A';
}
else
{
/* No, use the API */
Value = RtlUpcaseUnicodeChar(*Cp);
}
}
else
{
/* Reuse the char, it's already upcased */
Value = *Cp;
}
/* Multiply by a prime and add our value */
Hash *= 37;
Hash += Value;
}
/* Return the hash */
return Hash;
}
HCELL_INDEX
NTAPI
CmpFindSubKeyByHash(IN PHHIVE Hive,
IN PCM_KEY_FAST_INDEX FastIndex,
IN PUNICODE_STRING SearchName)
{
ULONG HashKey, i;
PCM_INDEX FastEntry;
/* Make sure it's really a hash */
ASSERT(FastIndex->Signature == CM_KEY_HASH_LEAF);
/* Compute the hash key for the name */
HashKey = CmpComputeHashKey(0, SearchName, FALSE);
/* Loop all the entries */
for (i = 0; i < FastIndex->Count; i++)
{
/* Get the entry */
FastEntry = &FastIndex->List[i];
/* Compare the hash first */
if (FastEntry->HashKey == HashKey)
{
/* Go ahead for a full compare */
if (!(CmpDoCompareKeyName(Hive, SearchName, FastEntry->Cell)))
{
/* It matched, return the cell */
return FastEntry->Cell;
}
}
}
/* If we got here then we failed */
return HCELL_NIL;
}
HCELL_INDEX
NTAPI
CmpFindSubKeyByName(IN PHHIVE Hive,
IN PCM_KEY_NODE Parent,
IN PUNICODE_STRING SearchName)
{
ULONG i;
PCM_KEY_INDEX IndexRoot;
HCELL_INDEX SubKey, CellToRelease;
ULONG Found;
/* Loop each storage type */
for (i = 0; i < Hive->StorageTypeCount; i++)
{
/* Make sure the parent node has subkeys */
if (Parent->SubKeyCounts[i])
{
/* Get the Index */
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
#if 0
/* Make sure we have one and that the cell is allocated */
ASSERT((IndexRoot == NULL) ||
HvIsCellAllocated(Hive, Parent->SubKeyLists[i]));
#endif
/* Fail if we don't actually have an index root */
if (!IndexRoot) return HCELL_NIL;
/* Get the cell we'll need to release */
CellToRelease = Parent->SubKeyLists[i];
/* Check if this is another index root */
if (IndexRoot->Signature == CM_KEY_INDEX_ROOT)
{
/* Lookup the name in the root */
Found = CmpFindSubKeyInRoot(Hive,
IndexRoot,
SearchName,
&SubKey);
/* Release the previous cell */
ASSERT(CellToRelease != HCELL_NIL);
HvReleaseCell(Hive, CellToRelease);
/* Make sure we found something valid */
if (Found < 0) break;
/* Get the new Index Root and set the new cell to be released */
if (SubKey == HCELL_NIL) continue;
CellToRelease = SubKey;
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, SubKey);
}
/* Make sure the signature is what we expect it to be */
ASSERT((IndexRoot->Signature == CM_KEY_INDEX_LEAF) ||
(IndexRoot->Signature == CM_KEY_FAST_LEAF) ||
(IndexRoot->Signature == CM_KEY_HASH_LEAF));
/* Check if this isn't a hashed leaf */
if (IndexRoot->Signature != CM_KEY_HASH_LEAF)
{
/* Find the subkey in the leaf */
Found = CmpFindSubKeyInLeaf(Hive,
IndexRoot,
SearchName,
&SubKey);
/* Release the previous cell */
ASSERT(CellToRelease != HCELL_NIL);
HvReleaseCell(Hive, CellToRelease);
/* Make sure we found a valid index */
if (Found < 0) break;
}
else
{
/* Find the subkey in the hash */
SubKey = CmpFindSubKeyByHash(Hive,
(PCM_KEY_FAST_INDEX)IndexRoot,
SearchName);
/* Release the previous cell */
ASSERT(CellToRelease != HCELL_NIL);
HvReleaseCell(Hive, CellToRelease);
}
/* Make sure we got a valid subkey and return it */
if (SubKey != HCELL_NIL) return SubKey;
}
}
/* If we got here, then we failed */
return HCELL_NIL;
}

View file

@ -0,0 +1,33 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmmapvw.c
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitHiveViewList(IN PCMHIVE Hive)
{
/* Initialize the list heads */
InitializeListHead(&Hive->LRUViewListHead);
InitializeListHead(&Hive->PinViewListHead);
/* Reset data */
Hive->MappedViews = 0;
Hive->PinnedViews = 0;
Hive->UseCount = 0;
}

View file

@ -0,0 +1,166 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmname.c
* PURPOSE: Configuration Manager - Name Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
LONG
NTAPI
CmpCompareCompressedName(IN PUNICODE_STRING SearchName,
IN PWCHAR CompressedName,
IN ULONG NameLength)
{
WCHAR *p;
CHAR *pp;
WCHAR p1, p2;
USHORT SearchLength;
LONG Result;
/* Set the pointers and length and then loop */
p = SearchName->Buffer;
pp = (PCHAR)CompressedName;
SearchLength = (SearchName->Length / sizeof(WCHAR));
while ((SearchLength) && (NameLength))
{
/* Get the characters */
p1 = *p++;
p2 = (WCHAR)(*pp++);
/* Check if we have a direct match */
if (p1 != p2)
{
/* See if they match and return result if they don't */
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
(LONG)RtlUpcaseUnicodeChar(p2);
if (Result) return Result;
}
/* Next chars */
SearchLength--;
NameLength--;
}
/* Return the difference directly */
return SearchLength - NameLength;
}
BOOLEAN
NTAPI
CmpFindNameInList(IN PHHIVE Hive,
IN PCHILD_LIST ChildList,
IN PUNICODE_STRING Name,
IN PULONG ChildIndex,
IN PHCELL_INDEX CellIndex)
{
PCELL_DATA CellData;
HCELL_INDEX CellToRelease = HCELL_NIL;
ULONG i;
PCM_KEY_VALUE KeyValue;
LONG Result;
UNICODE_STRING SearchName;
BOOLEAN Success;
/* Make sure there's actually something on the list */
if (ChildList->Count != 0)
{
/* Get the cell data */
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
if (!CellData)
{
/* Couldn't get the cell... tell the caller */
*CellIndex = HCELL_NIL;
return FALSE;
}
/* Now loop every entry */
for (i = 0; i < ChildList->Count; i++)
{
/* Check if we have a cell to release */
if (CellToRelease != HCELL_NIL)
{
/* Release it */
HvReleaseCell(Hive, CellToRelease);
CellToRelease = HCELL_NIL;
}
/* Get this value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
if (!KeyValue)
{
/* Return with no data found */
*CellIndex = HCELL_NIL;
Success = FALSE;
goto Return;
}
/* Save the cell to release */
CellToRelease = CellData->u.KeyList[i];
/* Check if it's a compressed value name */
if (KeyValue->Flags & VALUE_COMP_NAME)
{
/* Use the compressed name check */
Result = CmpCompareCompressedName(Name,
KeyValue->Name,
KeyValue->NameLength);
}
else
{
/* Setup the Unicode string */
SearchName.Length = KeyValue->NameLength;
SearchName.MaximumLength = SearchName.Length;
SearchName.Buffer = KeyValue->Name;
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
}
/* Check if we found it */
if (!Result)
{
/* We did...return info to caller */
if (ChildIndex) *ChildIndex = i;
*CellIndex = CellData->u.KeyList[i];
/* Set success state */
Success = TRUE;
goto Return;
}
}
/* Got to the end of the list */
if (ChildIndex) *ChildIndex = i;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
Success = TRUE;
goto Return;
}
/* Nothing found...check if the caller wanted more info */
ASSERT(ChildList->Count == 0);
if (ChildIndex) *ChildIndex = 0;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
return TRUE;
Return:
/* Release the first cell we got */
if (CellData) HvReleaseCell(Hive, ChildList->List);
/* Release the secondary one, if we have one */
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
return Success;
}

View file

@ -0,0 +1,75 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmparse.c
* PURPOSE: Configuration Manager - Object Manager Parse Interface
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
CmpGetNextName(IN OUT PUNICODE_STRING RemainingName,
OUT PUNICODE_STRING NextName,
OUT PBOOLEAN LastName)
{
BOOLEAN NameValid = TRUE;
/* Check if there's nothing left in the name */
if (!(RemainingName->Buffer) ||
(!RemainingName->Length) ||
!(*RemainingName->Buffer))
{
/* Clear the next name and set this as last */
*LastName = TRUE;
NextName->Buffer = NULL;
NextName->Length = 0;
return TRUE;
}
/* Check if we have a path separator */
if (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR)
{
/* Skip it */
RemainingName->Buffer++;
RemainingName->Length -= sizeof(WCHAR);
RemainingName->MaximumLength -= sizeof(WCHAR);
}
/* Start loop at where the current buffer is */
NextName->Buffer = RemainingName->Buffer;
while (TRUE)
{
/* Break out if we ran out or hit a path separator */
if (!(RemainingName->Length) ||
(*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR))
{
break;
}
/* Move to the next character */
RemainingName->Buffer++;
RemainingName->Length -= sizeof(WCHAR);
RemainingName->MaximumLength -= sizeof(WCHAR);
}
/* See how many chars we parsed and validate the length */
NextName->Length = (USHORT)((ULONG_PTR)RemainingName->Buffer -
(ULONG_PTR)NextName->Buffer);
if (NextName->Length > 512) NameValid = FALSE;
NextName->MaximumLength = NextName->Length;
/* If there's nothing left, we're last */
*LastName = !RemainingName->Length;
return NameValid;
}

View file

@ -0,0 +1,38 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmsecach.c
* PURPOSE: Configuration Manager - Security Cache
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitSecurityCache(IN PCMHIVE Hive)
{
ULONG i;
/* Reset data */
Hive->SecurityCount = 0;
Hive->SecurityCacheSize = 0;
Hive->SecurityHitHint = -1;
Hive->SecurityCache = NULL;
/* Loop every security hash */
for (i = 0; i < 64; i++)
{
/* Initialize it */
InitializeListHead(&Hive->SecurityHash[i]);
}
}

View file

@ -0,0 +1,125 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmvalue.c
* PURPOSE: Configuration Manager - Cell Values
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
HCELL_INDEX
NTAPI
CmpFindValueByName(IN PHHIVE Hive,
IN PCM_KEY_NODE KeyNode,
IN PUNICODE_STRING Name)
{
HCELL_INDEX CellIndex;
/* Call the main function */
if (!CmpFindNameInList(Hive,
&KeyNode->ValueList,
Name,
NULL,
&CellIndex))
{
/* Santy check */
ASSERT(CellIndex == HCELL_NIL);
}
/* Return the index */
return CellIndex;
}
BOOLEAN
NTAPI
CmpGetValueData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
IN PULONG Length,
OUT PVOID *Buffer,
OUT PBOOLEAN BufferAllocated,
OUT PHCELL_INDEX CellToRelease)
{
PAGED_CODE();
/* Sanity check */
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
/* Set failure defaults */
*BufferAllocated = FALSE;
*Buffer = NULL;
*CellToRelease = HCELL_NIL;
/* Check if this is a small key */
if (CmpIsKeyValueSmall(Length, Value->DataLength))
{
/* Return the data immediately */
*Buffer = &Value->Data;
return TRUE;
}
/* Check if this is a big cell */
if (CmpIsKeyValueBig(Hive, *Length))
{
/* FIXME: We don't support big cells */
DPRINT1("Unsupported cell type!\n");
while (TRUE);
}
/* Get the data from the cell */
*Buffer = HvGetCell(Hive, Value->Data);
if (!(*Buffer)) return FALSE;
/* Return success and the cell to be released */
*CellToRelease = Value->Data;
return TRUE;
}
PCELL_DATA
NTAPI
CmpValueToData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
OUT PULONG Length)
{
PCELL_DATA Buffer;
BOOLEAN BufferAllocated;
HCELL_INDEX CellToRelease;
PAGED_CODE();
/* Sanity check */
ASSERT(Hive->ReleaseCellRoutine == NULL);
/* Get the actual data */
if (!CmpGetValueData(Hive,
Value,
Length,
(PVOID)&Buffer,
&BufferAllocated,
&CellToRelease))
{
/* We failed */
ASSERT(BufferAllocated == FALSE);
ASSERT(Buffer == NULL);
return NULL;
}
/* This should never happen!*/
if (BufferAllocated)
{
/* Free the buffer and bugcheck */
ExFreePool(Buffer);
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
}
/* Otherwise, return the cell data */
return Buffer;
}

View file

@ -83,14 +83,23 @@
<file>pin.c</file>
<file>view.c</file>
</directory>
<directory name="config">
<file>cmboot.c</file>
<file>cmcontrl.c</file>
<file>cmdata.c</file>
<file>cmindex.c</file>
<file>cmmapvw.c</file>
<file>cmname.c</file>
<file>cmparse.c</file>
<file>cmsecach.c</file>
<file>cmvalue.c</file>
</directory>
<directory name="cm">
<file>import.c</file>
<file>ntfunc.c</file>
<file>regfile.c</file>
<file>registry.c</file>
<file>regobj.c</file>
<file>newcm.c</file>
<file>cmdata.c</file>
</directory>
<directory name="dbgk">
<file>dbgkutil.c</file>