[ros-diffs] [ion] 26666: - 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.

ion at svn.reactos.org ion at svn.reactos.org
Wed May 9 20:30:21 CEST 2007


Author: ion
Date: Wed May  9 22:30:21 2007
New Revision: 26666

URL: http://svn.reactos.org/svn/reactos?rev=26666&view=rev
Log:
- 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.

Added:
    trunk/reactos/ntoskrnl/config/
    trunk/reactos/ntoskrnl/config/cm.h
    trunk/reactos/ntoskrnl/config/cm_x.h
    trunk/reactos/ntoskrnl/config/cmboot.c
    trunk/reactos/ntoskrnl/config/cmcontrl.c
    trunk/reactos/ntoskrnl/config/cmdata.c
    trunk/reactos/ntoskrnl/config/cmindex.c
    trunk/reactos/ntoskrnl/config/cmmapvw.c
    trunk/reactos/ntoskrnl/config/cmname.c
    trunk/reactos/ntoskrnl/config/cmparse.c
    trunk/reactos/ntoskrnl/config/cmsecach.c
    trunk/reactos/ntoskrnl/config/cmvalue.c
Removed:
    trunk/reactos/ntoskrnl/cm/newcm.c
Modified:
    trunk/reactos/ntoskrnl/ntoskrnl.rbuild

Removed: trunk/reactos/ntoskrnl/cm/newcm.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/newcm.c?rev=26665&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/cm/newcm.c (original)
+++ trunk/reactos/ntoskrnl/cm/newcm.c (removed)
@@ -1,12 +1,0 @@
-#include "ntoskrnl.h"
-#include "cm.h"
-#include "debug.h"
-
-VOID
-NTAPI
-CmGetSystemControlValues(IN PVOID SystemHiveData,
-                         IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
-{
-    return;
-}
-

Added: trunk/reactos/ntoskrnl/config/cm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cm.h (added)
+++ trunk/reactos/ntoskrnl/config/cm.h Wed May  9 22:30:21 2007
@@ -1,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 at 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"

Added: trunk/reactos/ntoskrnl/config/cm_x.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm_x.h?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cm_x.h (added)
+++ trunk/reactos/ntoskrnl/config/cm_x.h Wed May  9 22:30:21 2007
@@ -1,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 at 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);           \
+}

Added: trunk/reactos/ntoskrnl/config/cmboot.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmboot.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmboot.c (added)
+++ trunk/reactos/ntoskrnl/config/cmboot.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Added: trunk/reactos/ntoskrnl/config/cmcontrl.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmcontrl.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmcontrl.c (added)
+++ trunk/reactos/ntoskrnl/config/cmcontrl.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Added: trunk/reactos/ntoskrnl/config/cmdata.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmdata.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmdata.c (added)
+++ trunk/reactos/ntoskrnl/config/cmdata.c Wed May  9 22:30:21 2007
@@ -1,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 at 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
+    }
+};

Added: trunk/reactos/ntoskrnl/config/cmindex.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmindex.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmindex.c (added)
+++ trunk/reactos/ntoskrnl/config/cmindex.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Added: trunk/reactos/ntoskrnl/config/cmmapvw.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmmapvw.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmmapvw.c (added)
+++ trunk/reactos/ntoskrnl/config/cmmapvw.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}
+

Added: trunk/reactos/ntoskrnl/config/cmname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmname.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmname.c (added)
+++ trunk/reactos/ntoskrnl/config/cmname.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Added: trunk/reactos/ntoskrnl/config/cmparse.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmparse.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmparse.c (added)
+++ trunk/reactos/ntoskrnl/config/cmparse.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Added: trunk/reactos/ntoskrnl/config/cmsecach.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmsecach.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmsecach.c (added)
+++ trunk/reactos/ntoskrnl/config/cmsecach.c Wed May  9 22:30:21 2007
@@ -1,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 at 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]);
+    }
+}

Added: trunk/reactos/ntoskrnl/config/cmvalue.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmvalue.c?rev=26666&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmvalue.c (added)
+++ trunk/reactos/ntoskrnl/config/cmvalue.c Wed May  9 22:30:21 2007
@@ -1,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 at 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;
+}

Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?rev=26666&r1=26665&r2=26666&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Wed May  9 22:30:21 2007
@@ -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>




More information about the Ros-diffs mailing list