mirror of
https://github.com/reactos/reactos.git
synced 2025-06-05 09:20:30 +00:00
- Implement CmGetSystemControlValues and all related low-level Cm functionality required to select the proper control set and read all the kernel variables during Phase 0 initialization. We can now read time-zone data, version, suite, language IDs and other important kernel variables in the lowest-level boot phase.
- New code uses cmlib from Filip Navara without any modification, and is fully compatible with reading Windows hives as well except XP's "Big value cells" (cells with > 2GB data) which aren't supported. - Create /config directory where the new Configuration Manager code lies. svn path=/trunk/; revision=26666
This commit is contained in:
parent
5aaa1671e7
commit
33ea79c7fe
13 changed files with 3312 additions and 14 deletions
|
@ -1,12 +0,0 @@
|
|||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#include "debug.h"
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmGetSystemControlValues(IN PVOID SystemHiveData,
|
||||
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
968
reactos/ntoskrnl/config/cm.h
Normal file
968
reactos/ntoskrnl/config/cm.h
Normal file
|
@ -0,0 +1,968 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/cm/cm.h
|
||||
* PURPOSE: Internal header for the Configuration Manager
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
#define _CM_
|
||||
#include "cmlib.h"
|
||||
|
||||
//
|
||||
// Define this if you want debugging support
|
||||
//
|
||||
#define _CM_DEBUG_ 0x00
|
||||
|
||||
//
|
||||
// These define the Debug Masks Supported
|
||||
//
|
||||
#define CM_HANDLE_DEBUG 0x01
|
||||
#define CM_NAMESPACE_DEBUG 0x02
|
||||
#define CM_SECURITY_DEBUG 0x04
|
||||
#define CM_REFERENCE_DEBUG 0x08
|
||||
#define CM_CALLBACK_DEBUG 0x10
|
||||
|
||||
//
|
||||
// Debug/Tracing support
|
||||
//
|
||||
#if _CM_DEBUG_
|
||||
#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
|
||||
#define CMTRACE DbgPrintEx
|
||||
#else
|
||||
#define CMTRACE(x, ...) \
|
||||
if (x & CmpTraceLevel) DbgPrint(__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define CMTRACE(x, ...) DPRINT(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Tag for all registry allocations
|
||||
//
|
||||
#define TAG_CM \
|
||||
TAG('C', 'm', ' ', ' ')
|
||||
|
||||
//
|
||||
// Hive operations
|
||||
//
|
||||
#define HINIT_CREATE 0
|
||||
#define HINIT_MEMORY 1
|
||||
#define HINIT_FILE 2
|
||||
#define HINIT_MEMORY_INPLACE 3
|
||||
#define HINIT_FLAT 4
|
||||
#define HINIT_MAPFILE 5
|
||||
|
||||
//
|
||||
// Hive flags
|
||||
//
|
||||
#define HIVE_VOLATILE 1
|
||||
#define HIVE_NOLAZYFLUSH 2
|
||||
|
||||
//
|
||||
// Hive types
|
||||
//
|
||||
#define HFILE_TYPE_PRIMARY 0
|
||||
#define HFILE_TYPE_ALTERNATE 1
|
||||
#define HFILE_TYPE_LOG 2
|
||||
#define HFILE_TYPE_EXTERNAL 3
|
||||
#define HFILE_TYPE_MAX 4
|
||||
|
||||
//
|
||||
// Hive sizes
|
||||
//
|
||||
#define HBLOCK_SIZE 0x1000
|
||||
#define HSECTOR_SIZE 0x200
|
||||
#define HSECTOR_COUNT 8
|
||||
|
||||
//
|
||||
// Hive versions
|
||||
//
|
||||
#define HSYS_MAJOR 1
|
||||
#define HSYS_MINOR 3
|
||||
#define HSYS_WHISTLER_BETA1 4
|
||||
|
||||
//
|
||||
// Cell Masks
|
||||
//
|
||||
#define HCELL_NIL 0
|
||||
#define HCELL_CACHED 1
|
||||
|
||||
//
|
||||
// Key Types
|
||||
//
|
||||
#define CM_KEY_INDEX_ROOT 0x6972
|
||||
#define CM_KEY_INDEX_LEAF 0x696c
|
||||
#define CM_KEY_FAST_LEAF 0x666c
|
||||
#define CM_KEY_HASH_LEAF 0x686c
|
||||
|
||||
//
|
||||
// CM_KEY_CONTROL_BLOCK Flags
|
||||
//
|
||||
#define CM_KCB_NO_SUBKEY 0x01
|
||||
#define CM_KCB_SUBKEY_ONE 0x02
|
||||
#define CM_KCB_SUBKEY_HINT 0x04
|
||||
#define CM_KCB_SYM_LINK_FOUND 0x08
|
||||
#define CM_KCB_KEY_NON_EXIST 0x10
|
||||
#define CM_KCB_NO_DELAY_CLOSE 0x20
|
||||
#define CM_KCB_INVALID_CACHED_INFO 0x40
|
||||
#define CM_KEY_READ_ONLY_KEY 0x80
|
||||
|
||||
//
|
||||
// CM_KEY_NODE Signature and Flags
|
||||
//
|
||||
#define CM_KEY_NODE_SIGNATURE 0x6B6E
|
||||
#define CM_LINK_NODE_SIGNATURE 0x6B6C
|
||||
#define KEY_IS_VOLATILE 0x01
|
||||
#define KEY_HIVE_EXIT 0x02
|
||||
#define KEY_HIVE_ENTRY 0x04
|
||||
#define KEY_NO_DELETE 0x08
|
||||
#define KEY_SYM_LINK 0x10
|
||||
#define KEY_COMP_NAME 0x20
|
||||
#define KEY_PREFEF_HANDLE 0x40
|
||||
#define KEY_VIRT_MIRRORED 0x80
|
||||
#define KEY_VIRT_TARGET 0x100
|
||||
#define KEY_VIRTUAL_STORE 0x200
|
||||
|
||||
//
|
||||
// CM_KEY_VALUE Signature and Flags
|
||||
//
|
||||
#define CM_KEY_VALUE_SIGNATURE 0x6b76
|
||||
#define CM_KEY_VALUE_SMALL 0x4
|
||||
#define CM_KEY_VALUE_BIG 0x3FD8
|
||||
#define CM_KEY_VALUE_SPECIAL_SIZE 0x80000000
|
||||
#define VALUE_COMP_NAME 0x0001
|
||||
|
||||
//
|
||||
// Number of various lists and hashes
|
||||
//
|
||||
#define CMP_SECURITY_HASH_LISTS 64
|
||||
#define CMP_MAX_CALLBACKS 100
|
||||
|
||||
//
|
||||
// Hashing Constants
|
||||
//
|
||||
#define CMP_HASH_IRRATIONAL 314159269
|
||||
#define CMP_HASH_PRIME 1000000007
|
||||
|
||||
//
|
||||
// CmpCreateKcb Flags
|
||||
//
|
||||
#define CMP_CREATE_FAKE_KCB 0x1
|
||||
#define CMP_LOCK_HASHES_FOR_KCB 0x2
|
||||
|
||||
//
|
||||
// Number of items that can fit inside an Allocation Page
|
||||
//
|
||||
#define CM_KCBS_PER_PAGE \
|
||||
PAGE_SIZE / sizeof(CM_KEY_CONTROL_BLOCK)
|
||||
#define CM_DELAYS_PER_PAGE \
|
||||
PAGE_SIZE / sizeof(CM_DELAYED_CLOSE_ENTRY)
|
||||
|
||||
//
|
||||
// Key Hash
|
||||
//
|
||||
typedef struct _CM_KEY_HASH
|
||||
{
|
||||
ULONG ConvKey;
|
||||
struct _CM_KEY_HASH *NextHash;
|
||||
PHHIVE KeyHive;
|
||||
HCELL_INDEX KeyCell;
|
||||
} CM_KEY_HASH, *PCM_KEY_HASH;
|
||||
|
||||
//
|
||||
// Key Hash Table Entry
|
||||
//
|
||||
typedef struct _CM_KEY_HASH_TABLE_ENTRY
|
||||
{
|
||||
EX_PUSH_LOCK Lock;
|
||||
PKTHREAD Owner;
|
||||
PCM_KEY_HASH Entry;
|
||||
} CM_KEY_HASH_TABLE_ENTRY, *PCM_KEY_HASH_TABLE_ENTRY;
|
||||
|
||||
//
|
||||
// Name Hash
|
||||
//
|
||||
typedef struct _CM_NAME_HASH
|
||||
{
|
||||
ULONG ConvKey;
|
||||
struct _CM_NAME_HASH *NextHash;
|
||||
USHORT NameLength;
|
||||
WCHAR Name[ANYSIZE_ARRAY];
|
||||
} CM_NAME_HASH, *PCM_NAME_HASH;
|
||||
|
||||
//
|
||||
// Name Hash Table Entry
|
||||
//
|
||||
typedef struct _CM_NAME_HASH_TABLE_ENTRY
|
||||
{
|
||||
EX_PUSH_LOCK Lock;
|
||||
PCM_NAME_HASH Entry;
|
||||
} CM_NAME_HASH_TABLE_ENTRY, *PCM_NAME_HASH_TABLE_ENTRY;
|
||||
|
||||
//
|
||||
// Key Security Cache
|
||||
//
|
||||
typedef struct _CM_KEY_SECURITY_CACHE
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
ULONG ConvKey;
|
||||
LIST_ENTRY List;
|
||||
ULONG DescriptorLength;
|
||||
SECURITY_DESCRIPTOR_RELATIVE Descriptor;
|
||||
} CM_KEY_SECURITY_CACHE, *PCM_KEY_SECURITY_CACHE;
|
||||
|
||||
//
|
||||
// Key Security Cache Entry
|
||||
//
|
||||
typedef struct _CM_KEY_SECURITY_CACHE_ENTRY
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
PCM_KEY_SECURITY_CACHE CachedSecurity;
|
||||
} CM_KEY_SECURITY_CACHE_ENTRY, *PCM_KEY_SECURITY_CACHE_ENTRY;
|
||||
|
||||
//
|
||||
// Cached Child List
|
||||
//
|
||||
typedef struct _CACHED_CHILD_LIST
|
||||
{
|
||||
ULONG Count;
|
||||
union
|
||||
{
|
||||
ULONG ValueList;
|
||||
struct _CM_KEY_CONTROL_BLOCK *RealKcb;
|
||||
};
|
||||
} CACHED_CHILD_LIST, *PCACHED_CHILD_LIST;
|
||||
|
||||
//
|
||||
// Index Hint Block
|
||||
//
|
||||
typedef struct _CM_INDEX_HINT_BLOCK
|
||||
{
|
||||
ULONG Count;
|
||||
ULONG HashKey[ANYSIZE_ARRAY];
|
||||
} CM_INDEX_HINT_BLOCK, *PCM_INDEX_HINT_BLOCK;
|
||||
|
||||
//
|
||||
// Key Reference
|
||||
//
|
||||
typedef struct _CM_KEY_REFERENCE
|
||||
{
|
||||
HCELL_INDEX KeyCell;
|
||||
PHHIVE KeyHive;
|
||||
} CM_KEY_REFERENCE, *PCM_KEY_REFERENCE;
|
||||
|
||||
//
|
||||
// Key Body
|
||||
//
|
||||
typedef struct _CM_KEY_BODY
|
||||
{
|
||||
ULONG Type;
|
||||
struct _CM_KEY_CONTROL_BLOCK *KeyControlBlock;
|
||||
struct _CM_NOTIFY_BLOCK *NotifyBlock;
|
||||
HANDLE ProcessID;
|
||||
ULONG Callers;
|
||||
PVOID CallerAddress[10];
|
||||
LIST_ENTRY KeyBodyList;
|
||||
} CM_KEY_BODY, *PCM_KEY_BODY;
|
||||
|
||||
//
|
||||
// Name Control Block (NCB)
|
||||
//
|
||||
typedef struct _CM_NAME_CONTROL_BLOCK
|
||||
{
|
||||
BOOLEAN Compressed;
|
||||
USHORT RefCount;
|
||||
union
|
||||
{
|
||||
CM_NAME_HASH NameHash;
|
||||
struct
|
||||
{
|
||||
ULONG ConvKey;
|
||||
PCM_KEY_HASH NextHash;
|
||||
USHORT NameLength;
|
||||
WCHAR Name[ANYSIZE_ARRAY];
|
||||
};
|
||||
};
|
||||
} CM_NAME_CONTROL_BLOCK, *PCM_NAME_CONTROL_BLOCK;
|
||||
|
||||
//
|
||||
// Key Control Block (KCB)
|
||||
//
|
||||
typedef struct _CM_KEY_CONTROL_BLOCK
|
||||
{
|
||||
USHORT RefCount;
|
||||
USHORT Flags;
|
||||
ULONG ExtFlags:8;
|
||||
ULONG PrivateAlloc:1;
|
||||
ULONG Delete:1;
|
||||
ULONG DelayedCloseIndex:12;
|
||||
ULONG TotalLevels:10;
|
||||
union
|
||||
{
|
||||
CM_KEY_HASH KeyHash;
|
||||
struct
|
||||
{
|
||||
ULONG ConvKey;
|
||||
PCM_KEY_HASH NextHash;
|
||||
PHHIVE KeyHive;
|
||||
HCELL_INDEX KeyCell;
|
||||
};
|
||||
};
|
||||
struct _CM_KEY_CONTROL_BLOCK *ParentKcb;
|
||||
PCM_NAME_CONTROL_BLOCK NameBlock;
|
||||
PCM_KEY_SECURITY_CACHE CachedSecurity;
|
||||
CACHED_CHILD_LIST ValueCache;
|
||||
PCM_INDEX_HINT_BLOCK IndexHint;
|
||||
ULONG HashKey;
|
||||
ULONG SubKeyCount;
|
||||
union
|
||||
{
|
||||
LIST_ENTRY KeyBodyListHead;
|
||||
LIST_ENTRY FreeListEntry;
|
||||
};
|
||||
PCM_KEY_BODY KeyBodyArray[4];
|
||||
PVOID DelayCloseEntry;
|
||||
LARGE_INTEGER KcbLastWriteTime;
|
||||
USHORT KcbMaxNameLen;
|
||||
USHORT KcbMaxValueNameLen;
|
||||
ULONG KcbMaxValueDataLen;
|
||||
ULONG InDelayClose;
|
||||
} CM_KEY_CONTROL_BLOCK, *PCM_KEY_CONTROL_BLOCK;
|
||||
|
||||
//
|
||||
// Notify Block
|
||||
//
|
||||
typedef struct _CM_NOTIFY_BLOCK
|
||||
{
|
||||
LIST_ENTRY HiveList;
|
||||
LIST_ENTRY PostList;
|
||||
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
||||
PCM_KEY_BODY KeyBody;
|
||||
ULONG Filter:29;
|
||||
ULONG WatchTree:30;
|
||||
ULONG NotifyPending:31;
|
||||
} CM_NOTIFY_BLOCK, *PCM_NOTIFY_BLOCK;
|
||||
|
||||
//
|
||||
// Re-map Block
|
||||
//
|
||||
typedef struct _CM_CELL_REMAP_BLOCK
|
||||
{
|
||||
HCELL_INDEX OldCell;
|
||||
HCELL_INDEX NewCell;
|
||||
} CM_CELL_REMAP_BLOCK, *PCM_CELL_REMAP_BLOCK;
|
||||
|
||||
//
|
||||
// Allocation Page
|
||||
//
|
||||
typedef struct _CM_ALLOC_PAGE
|
||||
{
|
||||
ULONG FreeCount;
|
||||
ULONG Reserved;
|
||||
PVOID AllocPage;
|
||||
} CM_ALLOC_PAGE, *PCM_ALLOC_PAGE;
|
||||
|
||||
//
|
||||
// Delayed Close Entry
|
||||
//
|
||||
typedef struct _CM_DELAYED_CLOSE_ENTRY
|
||||
{
|
||||
LIST_ENTRY DelayedLRUList;
|
||||
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
||||
} CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY;
|
||||
|
||||
//
|
||||
// Delayed KCB Dereference Entry
|
||||
//
|
||||
typedef struct _CM_DELAY_DEREF_KCB_ITEM
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PCM_KEY_CONTROL_BLOCK Kcb;
|
||||
} CM_DELAY_DEREF_KCB_ITEM, *PCM_DELAY_DEREF_KCB_ITEM;
|
||||
|
||||
//
|
||||
// Use Count Log and Entry
|
||||
//
|
||||
typedef struct _CM_USE_COUNT_LOG_ENTRY
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
PVOID Stack[7];
|
||||
} CM_USE_COUNT_LOG_ENTRY, *PCM_USE_COUNT_LOG_ENTRY;
|
||||
|
||||
typedef struct _CM_USE_COUNT_LOG
|
||||
{
|
||||
USHORT Next;
|
||||
USHORT Size;
|
||||
CM_USE_COUNT_LOG_ENTRY Log[32];
|
||||
} CM_USE_COUNT_LOG, *PCM_USE_COUNT_LOG;
|
||||
|
||||
//
|
||||
// Configuration Manager Hive Structure
|
||||
//
|
||||
typedef struct _CMHIVE
|
||||
{
|
||||
HHIVE Hive;
|
||||
HANDLE FileHandles[3];
|
||||
LIST_ENTRY NotifyList;
|
||||
LIST_ENTRY HiveList;
|
||||
EX_PUSH_LOCK HiveLock;
|
||||
PKTHREAD HiveLockOwner;
|
||||
PKGUARDED_MUTEX ViewLock;
|
||||
PKTHREAD ViewLockOwner;
|
||||
EX_PUSH_LOCK WriterLock;
|
||||
PKTHREAD WriterLockOwner;
|
||||
PERESOURCE FlusherLock;
|
||||
EX_PUSH_LOCK SecurityLock;
|
||||
PKTHREAD HiveSecurityLockOwner;
|
||||
LIST_ENTRY LRUViewListHead;
|
||||
LIST_ENTRY PinViewListHead;
|
||||
PFILE_OBJECT FileObject;
|
||||
UNICODE_STRING FileFullPath;
|
||||
UNICODE_STRING FileUserName;
|
||||
USHORT MappedViews;
|
||||
USHORT PinnedViews;
|
||||
ULONG UseCount;
|
||||
ULONG SecurityCount;
|
||||
ULONG SecurityCacheSize;
|
||||
LONG SecurityHitHint;
|
||||
PCM_KEY_SECURITY_CACHE_ENTRY SecurityCache;
|
||||
LIST_ENTRY SecurityHash[CMP_SECURITY_HASH_LISTS];
|
||||
PKEVENT UnloadEvent;
|
||||
PCM_KEY_CONTROL_BLOCK RootKcb;
|
||||
BOOLEAN Frozen;
|
||||
PWORK_QUEUE_ITEM UnloadWorkItem;
|
||||
BOOLEAN GrowOnlyMode;
|
||||
ULONG GrowOffset;
|
||||
LIST_ENTRY KcbConvertListHead;
|
||||
LIST_ENTRY KnodeConvertListHead;
|
||||
PCM_CELL_REMAP_BLOCK CellRemapArray;
|
||||
CM_USE_COUNT_LOG UseCountLog;
|
||||
CM_USE_COUNT_LOG LockHiveLog;
|
||||
ULONG Flags;
|
||||
LIST_ENTRY TrustClassEntry;
|
||||
ULONG FlushCount;
|
||||
BOOLEAN HiveIsLoading;
|
||||
PKTHREAD CreatorOwner;
|
||||
} CMHIVE, *PCMHIVE;
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _CM_VIEW_OF_FILE
|
||||
{
|
||||
LIST_ENTRY LRUViewList;
|
||||
LIST_ENTRY PinViewList;
|
||||
ULONG FileOffset;
|
||||
ULONG Size;
|
||||
PULONG ViewAddress;
|
||||
PVOID Bcb;
|
||||
ULONG UseCount;
|
||||
} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
|
||||
|
||||
typedef struct _CHILD_LIST
|
||||
{
|
||||
ULONG Count;
|
||||
HCELL_INDEX List;
|
||||
} CHILD_LIST, *PCHILD_LIST;
|
||||
|
||||
typedef struct _CM_KEY_NODE
|
||||
{
|
||||
USHORT Id;
|
||||
USHORT Flags;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG Spare;
|
||||
HCELL_INDEX Parent;
|
||||
ULONG SubKeyCounts[HvMaxStorageType];
|
||||
HCELL_INDEX SubKeyLists[HvMaxStorageType];
|
||||
CHILD_LIST ValueList;
|
||||
HCELL_INDEX SecurityKeyOffset;
|
||||
HCELL_INDEX ClassNameOffset;
|
||||
ULONG MaxNameLen;
|
||||
ULONG MaxClassLen;
|
||||
ULONG MaxValueNameLen;
|
||||
ULONG MaxValueDataLen;
|
||||
ULONG WorkVar;
|
||||
USHORT NameLength;
|
||||
USHORT ClassSize;
|
||||
WCHAR Name[0];
|
||||
} CM_KEY_NODE, *PCM_KEY_NODE;
|
||||
|
||||
typedef struct _VALUE_LIST_CELL
|
||||
{
|
||||
HCELL_INDEX ValueOffset[0];
|
||||
} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
|
||||
|
||||
typedef struct _CM_KEY_VALUE
|
||||
{
|
||||
USHORT Signature; // "kv"
|
||||
USHORT NameLength; // length of Name
|
||||
ULONG DataLength; // length of datas in the cell pointed by DataOffset
|
||||
HCELL_INDEX Data;// datas are here if high bit of DataSize is set
|
||||
ULONG Type;
|
||||
USHORT Flags;
|
||||
USHORT Unused1;
|
||||
WCHAR Name[0]; /* warning : not zero terminated */
|
||||
} CM_KEY_VALUE, *PCM_KEY_VALUE;
|
||||
|
||||
typedef struct _CM_KEY_SECURITY
|
||||
{
|
||||
USHORT Signature; // "sk"
|
||||
USHORT Reserved;
|
||||
HCELL_INDEX Flink;
|
||||
HCELL_INDEX Blink;
|
||||
ULONG ReferenceCount;
|
||||
ULONG DescriptorLength;
|
||||
//SECURITY_DESCRIPTOR_RELATIVE Descriptor;
|
||||
UCHAR Data[0];
|
||||
} CM_KEY_SECURITY, *PCM_KEY_SECURITY;
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
//
|
||||
// Generic Index Entry
|
||||
//
|
||||
typedef struct _CM_INDEX
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
union
|
||||
{
|
||||
UCHAR NameHint[4];
|
||||
ULONG HashKey;
|
||||
};
|
||||
} CM_INDEX, *PCM_INDEX;
|
||||
|
||||
//
|
||||
// Key Index
|
||||
//
|
||||
typedef struct _CM_KEY_INDEX
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Count;
|
||||
HCELL_INDEX List[ANYSIZE_ARRAY];
|
||||
} CM_KEY_INDEX, *PCM_KEY_INDEX;
|
||||
|
||||
//
|
||||
// Fast/Hash Key Index
|
||||
//
|
||||
typedef struct _CM_KEY_FAST_INDEX
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Count;
|
||||
CM_INDEX List[ANYSIZE_ARRAY];
|
||||
} CM_KEY_FAST_INDEX, *PCM_KEY_FAST_INDEX;
|
||||
|
||||
//
|
||||
// Cell Data
|
||||
//
|
||||
typedef struct _CELL_DATA
|
||||
{
|
||||
union
|
||||
{
|
||||
CM_KEY_NODE KeyNode;
|
||||
CM_KEY_VALUE KeyValue;
|
||||
CM_KEY_SECURITY KeySecurity;
|
||||
CM_KEY_INDEX KeyIndex;
|
||||
HCELL_INDEX KeyList[ANYSIZE_ARRAY];
|
||||
WCHAR KeyString[ANYSIZE_ARRAY];
|
||||
} u;
|
||||
} CELL_DATA, *PCELL_DATA;
|
||||
|
||||
//
|
||||
// Cached Value Index
|
||||
//
|
||||
typedef struct _CM_CACHED_VALUE_INDEX
|
||||
{
|
||||
HCELL_INDEX CellIndex;
|
||||
union
|
||||
{
|
||||
CELL_DATA CellData;
|
||||
ULONG_PTR List[ANYSIZE_ARRAY];
|
||||
} Data;
|
||||
} CM_CACHED_VALUE_INDEX, *PCM_CACHED_VALUE_INDEX;
|
||||
|
||||
//
|
||||
// Cached Value
|
||||
//
|
||||
typedef struct _CM_CACHED_VALUE
|
||||
{
|
||||
USHORT DataCacheType;
|
||||
USHORT ValueKeySize;
|
||||
CM_KEY_VALUE KeyValue;
|
||||
} CM_CACHED_VALUE, *PCM_CACHED_VALUE;
|
||||
|
||||
//
|
||||
// Hive List Entry
|
||||
//
|
||||
typedef struct _HIVE_LIST_ENTRY
|
||||
{
|
||||
PWCHAR FileName;
|
||||
PWCHAR BaseName;
|
||||
PWCHAR RegRootName;
|
||||
PCMHIVE CmHive;
|
||||
ULONG HHiveFlags;
|
||||
ULONG CmHiveFlags;
|
||||
PCMHIVE CmHive2;
|
||||
BOOLEAN ThreadFinished;
|
||||
BOOLEAN ThreadStarted;
|
||||
BOOLEAN Allocate;
|
||||
BOOLEAN WinPERequired;
|
||||
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
|
||||
|
||||
//
|
||||
// Parse context for Key Object
|
||||
//
|
||||
typedef struct _CM_PARSE_CONTEXT
|
||||
{
|
||||
ULONG TitleIndex;
|
||||
UNICODE_STRING Class;
|
||||
ULONG CreateOptions;
|
||||
ULONG Disposition;
|
||||
CM_KEY_REFERENCE ChildHive;
|
||||
BOOLEAN CreateLink;
|
||||
BOOLEAN Flag2;
|
||||
HANDLE PredefinedHandle;
|
||||
ULONG PostActions;
|
||||
} CM_PARSE_CONTEXT, *PCM_PARSE_CONTEXT;
|
||||
|
||||
//
|
||||
// System Control Vector
|
||||
//
|
||||
typedef struct _CM_SYSTEM_CONTROL_VECTOR
|
||||
{
|
||||
PWCHAR KeyPath;
|
||||
PWCHAR ValueName;
|
||||
PVOID Buffer;
|
||||
PULONG BufferLength;
|
||||
PULONG Type;
|
||||
} CM_SYSTEM_CONTROL_VECTOR, *PCM_SYSTEM_CONTROL_VECTOR;
|
||||
|
||||
//
|
||||
// Mapped View Hive Functions
|
||||
//
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitHiveViewList(
|
||||
IN PCMHIVE Hive
|
||||
);
|
||||
|
||||
//
|
||||
// Security Cache Functions
|
||||
//
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitSecurityCache(
|
||||
IN PCMHIVE Hive
|
||||
);
|
||||
|
||||
//
|
||||
// Registry Validation Functions
|
||||
//
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmCheckRegistry(
|
||||
IN PCMHIVE Hive,
|
||||
IN BOOLEAN CleanFlag
|
||||
);
|
||||
|
||||
//
|
||||
// Notification Routines
|
||||
//
|
||||
VOID
|
||||
CmpReportNotify(
|
||||
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN ULONG Filter
|
||||
);
|
||||
|
||||
//
|
||||
// KCB Cache/Delay Routines
|
||||
//
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitializeCache(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitializeCmAllocations(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitializeKcbDelayedDeref(
|
||||
VOID
|
||||
);
|
||||
|
||||
//
|
||||
// Key Object Routines
|
||||
//
|
||||
VOID
|
||||
NTAPI
|
||||
CmpCloseKeyObject(
|
||||
IN PEPROCESS Process OPTIONAL,
|
||||
IN PVOID Object,
|
||||
IN ACCESS_MASK GrantedAccess,
|
||||
IN ULONG ProcessHandleCount,
|
||||
IN ULONG SystemHandleCount
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpDeleteKeyObject(
|
||||
IN PVOID Object
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpParseKey(
|
||||
IN PVOID ParseObject,
|
||||
IN PVOID ObjectType,
|
||||
IN OUT PACCESS_STATE AccessState,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN ULONG Attributes,
|
||||
IN OUT PUNICODE_STRING CompleteName,
|
||||
IN OUT PUNICODE_STRING RemainingName,
|
||||
IN OUT PVOID Context OPTIONAL,
|
||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
||||
OUT PVOID *Object
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpSecurityMethod(
|
||||
IN PVOID Object,
|
||||
IN SECURITY_OPERATION_CODE OperationType,
|
||||
IN PSECURITY_INFORMATION SecurityInformation,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN OUT PULONG CapturedLength,
|
||||
IN OUT PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
|
||||
IN POOL_TYPE PoolType,
|
||||
IN PGENERIC_MAPPING GenericMapping
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpQueryKeyName(
|
||||
IN PVOID Object,
|
||||
IN BOOLEAN HasObjectName,
|
||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ReturnLength,
|
||||
IN KPROCESSOR_MODE AccessMode
|
||||
);
|
||||
|
||||
//
|
||||
// Hive Routines
|
||||
//
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpInitializeHive(
|
||||
OUT PCMHIVE *CmHive,
|
||||
IN ULONG Operation,
|
||||
IN ULONG Flags,
|
||||
IN ULONG FileType,
|
||||
IN PVOID HiveData,
|
||||
IN HANDLE Primary,
|
||||
IN HANDLE Alternate,
|
||||
IN HANDLE Log,
|
||||
IN HANDLE External,
|
||||
IN PUNICODE_STRING FileName
|
||||
);
|
||||
|
||||
PSECURITY_DESCRIPTOR
|
||||
NTAPI
|
||||
CmpHiveRootSecurityDescriptor(
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpLinkHiveToMaster(
|
||||
IN PUNICODE_STRING LinkName,
|
||||
IN HANDLE RootDirectory,
|
||||
IN PCMHIVE CmHive,
|
||||
IN BOOLEAN Allocate,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
);
|
||||
|
||||
//
|
||||
// Registry Utility Functions
|
||||
//
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpTestRegistryLockExclusive(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpLockRegistryExclusive(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpUnlockRegistry(
|
||||
VOID
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
CmpAllocateDelayItem(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpFreeDelayItem(
|
||||
PVOID Entry
|
||||
);
|
||||
|
||||
//
|
||||
// KCB Functions
|
||||
//
|
||||
PCM_KEY_CONTROL_BLOCK
|
||||
NTAPI
|
||||
CmpCreateKcb(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Index,
|
||||
IN PCM_KEY_NODE Node,
|
||||
IN PCM_KEY_CONTROL_BLOCK Parent,
|
||||
IN ULONG Flags,
|
||||
IN PUNICODE_STRING KeyName
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpDereferenceKcbWithLock(
|
||||
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||
IN BOOLEAN LockHeldExclusively
|
||||
);
|
||||
|
||||
//
|
||||
// Name Functions
|
||||
//
|
||||
LONG
|
||||
NTAPI
|
||||
CmpCompareCompressedName(
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN PWCHAR CompressedName,
|
||||
IN ULONG NameLength
|
||||
);
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
CmpNameSize(
|
||||
IN PHHIVE Hive,
|
||||
IN PUNICODE_STRING Name
|
||||
);
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
CmpCopyName(
|
||||
IN PHHIVE Hive,
|
||||
IN PWCHAR Destination,
|
||||
IN PUNICODE_STRING Source
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpFindNameInList(
|
||||
IN PHHIVE Hive,
|
||||
IN PCHILD_LIST ChildList,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN PULONG ChildIndex,
|
||||
IN PHCELL_INDEX CellIndex
|
||||
);
|
||||
|
||||
//
|
||||
// Parse Routines
|
||||
//
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpGetNextName(
|
||||
IN OUT PUNICODE_STRING RemainingName,
|
||||
OUT PUNICODE_STRING NextName,
|
||||
OUT PBOOLEAN LastName
|
||||
);
|
||||
|
||||
//
|
||||
// Flush Routines
|
||||
//
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpFlushEntireRegistry(
|
||||
IN BOOLEAN ForceFlush
|
||||
);
|
||||
|
||||
//
|
||||
// Cell Index Routines
|
||||
//
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindSubKeyByName(
|
||||
IN PHHIVE Hive,
|
||||
IN PCM_KEY_NODE Parent,
|
||||
IN PUNICODE_STRING SearchName
|
||||
);
|
||||
|
||||
//
|
||||
// Cell Value Routines
|
||||
//
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindValueByName(
|
||||
IN PHHIVE Hive,
|
||||
IN PCM_KEY_NODE KeyNode,
|
||||
IN PUNICODE_STRING Name
|
||||
);
|
||||
|
||||
PCELL_DATA
|
||||
NTAPI
|
||||
CmpValueToData(
|
||||
IN PHHIVE Hive,
|
||||
IN PCM_KEY_VALUE Value,
|
||||
OUT PULONG Length
|
||||
);
|
||||
|
||||
//
|
||||
// Boot Routines
|
||||
//
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindControlSet(
|
||||
IN PHHIVE SystemHive,
|
||||
IN HCELL_INDEX RootCell,
|
||||
IN PUNICODE_STRING SelectKeyName,
|
||||
OUT PBOOLEAN AutoSelect
|
||||
);
|
||||
|
||||
//
|
||||
// Global variables accessible from all of Cm
|
||||
//
|
||||
extern BOOLEAN CmpSpecialBootCondition;
|
||||
extern BOOLEAN CmpFlushOnLockRelease;
|
||||
extern EX_PUSH_LOCK CmpHiveListHeadLock;
|
||||
extern LIST_ENTRY CmpHiveListHead;
|
||||
extern POBJECT_TYPE CmpKeyObjectType;
|
||||
extern ERESOURCE CmpRegistryLock;
|
||||
extern PCM_KEY_HASH_TABLE_ENTRY *CmpCacheTable;
|
||||
extern PCM_NAME_HASH_TABLE_ENTRY *CmpNameCacheTable;
|
||||
extern KGUARDED_MUTEX CmpDelayedCloseTableLock;
|
||||
extern CMHIVE CmControlHive;
|
||||
extern WCHAR CmDefaultLanguageId[];
|
||||
extern ULONG CmDefaultLanguageIdLength;
|
||||
extern ULONG CmDefaultLanguageIdType;
|
||||
extern WCHAR CmInstallUILanguageId[];
|
||||
extern ULONG CmInstallUILanguageIdLength;
|
||||
extern ULONG CmInstallUILanguageIdType;
|
||||
extern LANGID PsInstallUILanguageId;
|
||||
extern LANGID PsDefaultUILanguageId;
|
||||
extern CM_SYSTEM_CONTROL_VECTOR CmControlVector[];
|
||||
|
||||
//
|
||||
// Inlined functions
|
||||
//
|
||||
#include "cm_x.h"
|
143
reactos/ntoskrnl/config/cm_x.h
Normal file
143
reactos/ntoskrnl/config/cm_x.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/cm/cm_x.h
|
||||
* PURPOSE: Inlined Functions for the Configuration Manager
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
//
|
||||
// Returns whether or not this is a small valued key
|
||||
//
|
||||
BOOLEAN
|
||||
FORCEINLINE
|
||||
CmpIsKeyValueSmall(OUT PULONG RealLength,
|
||||
IN ULONG Length)
|
||||
{
|
||||
/* Check if the length has the special size value */
|
||||
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
|
||||
{
|
||||
/* It does, so this is a small key: return the real length */
|
||||
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This is not a small key, return the length we read */
|
||||
*RealLength = Length;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns whether or not this is a big valued key
|
||||
//
|
||||
BOOLEAN
|
||||
FORCEINLINE
|
||||
CmpIsKeyValueBig(IN PHHIVE Hive,
|
||||
IN ULONG Length)
|
||||
{
|
||||
/* Check if the hive is XP Beta 1 or newer */
|
||||
if (Hive->Version >= HSYS_WHISTLER_BETA1)
|
||||
{
|
||||
/* Check if the key length is valid for a big value key */
|
||||
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
|
||||
{
|
||||
/* Yes, this value is big */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not a big value key */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the hashkey corresponding to a convkey
|
||||
//
|
||||
#define GET_HASH_KEY(ConvKey) \
|
||||
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
|
||||
|
||||
//
|
||||
// Returns the index into the hash table, or the entry itself
|
||||
//
|
||||
#define GET_HASH_INDEX(ConvKey) \
|
||||
GET_HASH_KEY(ConvKey) % CmpHashTableSize
|
||||
#define GET_HASH_ENTRY(Table, ConvKey) \
|
||||
(*Table[GET_HASH_INDEX(ConvKey)])
|
||||
|
||||
//
|
||||
// Returns whether or not the cell is cached
|
||||
//
|
||||
#define CMP_IS_CELL_CACHED(c) \
|
||||
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
|
||||
|
||||
//
|
||||
// Return data from a cached cell
|
||||
//
|
||||
#define CMP_GET_CACHED_CELL(c) \
|
||||
(ULONG_PTR)((c) & ~HCELL_CACHED)
|
||||
#define CMP_GET_CACHED_DATA(c) \
|
||||
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
|
||||
#define CMP_GET_CACHED_INDEX(c) \
|
||||
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
|
||||
#define CMP_GET_CACHED_VALUE(c) \
|
||||
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
|
||||
|
||||
//
|
||||
// Makes sure that the registry is locked
|
||||
//
|
||||
#define CMP_ASSERT_REGISTRY_LOCK() \
|
||||
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
||||
(CmpTestRegistryLock() == TRUE))
|
||||
|
||||
//
|
||||
// Makes sure that the registry is exclusively locked
|
||||
//
|
||||
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
|
||||
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
||||
(CmpTestRegistryLockExclusive() == TRUE))
|
||||
|
||||
//
|
||||
// Checks if a KCB is exclusively locked
|
||||
//
|
||||
#define CmpIsKcbLockedExclusive(k) \
|
||||
(GET_HASH_ENTRY(CmpCacheTable, \
|
||||
(k)->ConvKey).Owner == KeGetCurrentThread())
|
||||
|
||||
//
|
||||
// Exclusively acquires a KCB
|
||||
//
|
||||
#define CmpAcquireKcbLockExclusive(k) \
|
||||
{ \
|
||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||
(k)->ConvKey).Lock); \
|
||||
GET_HASH_ENTRY(CmpCacheTable, \
|
||||
(k)->ConvKey).Owner = KeGetCurrentThread(); \
|
||||
}
|
||||
|
||||
//
|
||||
// Releases an exlusively or shared acquired KCB
|
||||
//
|
||||
#define CmpReleaseKcbLock(k) \
|
||||
{ \
|
||||
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
|
||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||
(k)->ConvKey).Lock); \
|
||||
}
|
||||
|
||||
//
|
||||
// Exclusively acquires an NCB
|
||||
//
|
||||
#define CmpAcquireNcbLockExclusive(n) \
|
||||
{ \
|
||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||
(n)->ConvKey).Lock); \
|
||||
}
|
||||
|
||||
//
|
||||
// Releases an exlusively or shared acquired NCB
|
||||
//
|
||||
#define CmpReleaseNcbLock(k) \
|
||||
{ \
|
||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||
(k)->ConvKey).Lock); \
|
||||
}
|
127
reactos/ntoskrnl/config/cmboot.c
Normal file
127
reactos/ntoskrnl/config/cmboot.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmboot.c
|
||||
* PURPOSE: Configuration Manager - Boot Initialization
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindControlSet(IN PHHIVE SystemHive,
|
||||
IN HCELL_INDEX RootCell,
|
||||
IN PUNICODE_STRING SelectKeyName,
|
||||
OUT PBOOLEAN AutoSelect)
|
||||
{
|
||||
UNICODE_STRING KeyName;
|
||||
PCM_KEY_NODE Node;
|
||||
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
|
||||
HCELL_INDEX CurrentValueCell;
|
||||
PCM_KEY_VALUE KeyValue;
|
||||
ULONG Length;
|
||||
PULONG ControlSetId;
|
||||
ANSI_STRING ControlSetAnsiName;
|
||||
CHAR Buffer[128];
|
||||
WCHAR WideBuffer[128];
|
||||
NTSTATUS Status;
|
||||
PULONG CurrentData;
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||
|
||||
/* Get the Select subkey */
|
||||
RtlInitUnicodeString(&KeyName, L"select");
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||
if (SelectCell == HCELL_NIL) return SelectCell;
|
||||
|
||||
/* Get AutoSelect value */
|
||||
RtlInitUnicodeString(&KeyName, L"AutoSelect");
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||
if (AutoSelectCell == HCELL_NIL)
|
||||
{
|
||||
/* Assume TRUE if the value is missing. */
|
||||
*AutoSelect = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the value */
|
||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
|
||||
if (KeyValue == NULL) return HCELL_NIL;
|
||||
|
||||
/* Convert it to a boolean */
|
||||
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
|
||||
}
|
||||
|
||||
/* Now find the control set being looked up */
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
|
||||
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
|
||||
|
||||
/* Read the value (corresponding to the CCS ID) */
|
||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
|
||||
if (!KeyValue) return HCELL_NIL;
|
||||
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
|
||||
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
|
||||
|
||||
/* Now build an Ansi String for the CCS's Name */
|
||||
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
|
||||
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
|
||||
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
|
||||
ControlSetAnsiName.Buffer = Buffer;
|
||||
|
||||
/* And convert it to Unicode... */
|
||||
KeyName.MaximumLength = 256;
|
||||
KeyName.Buffer = WideBuffer;
|
||||
Status = RtlAnsiStringToUnicodeString(&KeyName,
|
||||
&ControlSetAnsiName,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status)) return HCELL_NIL;
|
||||
|
||||
/* Now open it */
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
|
||||
|
||||
/* Get the value of the "Current" CCS */
|
||||
RtlInitUnicodeString(&KeyName, L"Current");
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||
|
||||
/* Make sure it exists */
|
||||
if (CurrentValueCell != HCELL_NIL)
|
||||
{
|
||||
/* Get the current value and make sure its a ULONG */
|
||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
|
||||
if (!KeyValue) return HCELL_NIL;
|
||||
if (KeyValue->Type == REG_DWORD)
|
||||
{
|
||||
/* Get the data and update it */
|
||||
CurrentData = (PULONG)CmpValueToData(SystemHive,
|
||||
KeyValue,
|
||||
&Length);
|
||||
if (!CurrentData) return HCELL_NIL;
|
||||
*CurrentData = *ControlSetId;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the CCS Cell */
|
||||
return ControlSetCell;
|
||||
}
|
262
reactos/ntoskrnl/config/cmcontrl.c
Normal file
262
reactos/ntoskrnl/config/cmcontrl.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmcontrl.c
|
||||
* PURPOSE: Configuration Manager - Control Set Management
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
LANGID
|
||||
NTAPI
|
||||
CmpConvertLangId(IN LPWSTR Name,
|
||||
IN ULONG NameLength)
|
||||
{
|
||||
ULONG i;
|
||||
WCHAR p;
|
||||
LANGID LangId = 0;
|
||||
ULONG IdCode;
|
||||
|
||||
/* Convert the length in chars and loop */
|
||||
NameLength = NameLength / sizeof(WCHAR);
|
||||
for (i = 0; i < NameLength; i++)
|
||||
{
|
||||
/* Get the character */
|
||||
p = Name[i];
|
||||
|
||||
/* Handle each case */
|
||||
if ((p >= L'0') && (p <= L'9'))
|
||||
{
|
||||
/* Handle digits*/
|
||||
IdCode = p - L'0';
|
||||
}
|
||||
else if ((p >= L'A') && (p <= L'F'))
|
||||
{
|
||||
/* Handle upper-case letters */
|
||||
IdCode = p - L'A' + 10;
|
||||
}
|
||||
else if ((p >= L'a') && (p <= L'f'))
|
||||
{
|
||||
/* Handle lower-case letters */
|
||||
IdCode = p - L'a' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unhandled case, return what we have till now */
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the ID Code is >= 16, then we're done */
|
||||
if (IdCode >= 16) break;
|
||||
|
||||
/* Build the Language ID */
|
||||
LangId = (LangId << 4) | (LANGID)IdCode;
|
||||
}
|
||||
|
||||
/* Return the Language ID */
|
||||
return LangId;
|
||||
}
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpWalkPath(IN PHHIVE SystemHive,
|
||||
IN HCELL_INDEX ParentCell,
|
||||
IN LPWSTR Path)
|
||||
{
|
||||
UNICODE_STRING UnicodePath, NextName;
|
||||
BOOLEAN LastName;
|
||||
HCELL_INDEX CurrentCell = ParentCell;
|
||||
PCM_KEY_NODE Node;
|
||||
|
||||
/* We shouldn't have a release routine at this point */
|
||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||
|
||||
/* Initialize the Unicode path and start looping */
|
||||
RtlInitUnicodeString(&UnicodePath, Path);
|
||||
while (TRUE)
|
||||
{
|
||||
/* Get the next name */
|
||||
CmpGetNextName(&UnicodePath, &NextName, &LastName);
|
||||
if (!NextName.Length) return CurrentCell;
|
||||
|
||||
/* Get the subkey */
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
|
||||
if (!Node) return HCELL_NIL;
|
||||
CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
|
||||
if (CurrentCell == HCELL_NIL) return CurrentCell;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmGetSystemControlValues(IN PVOID SystemHiveData,
|
||||
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
|
||||
{
|
||||
PHHIVE SystemHive = (PHHIVE)&CmControlHive;
|
||||
NTSTATUS Status;
|
||||
HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
|
||||
ULONG Length, DataSize;
|
||||
PCM_KEY_NODE Node;
|
||||
PCM_KEY_VALUE ValueData;
|
||||
UNICODE_STRING KeyName;
|
||||
BOOLEAN Auto, IsSmallKey;
|
||||
PVOID Buffer;
|
||||
|
||||
/* Initialize the Hive View List and the security cache */
|
||||
RtlZeroMemory(SystemHive, sizeof(SystemHive));
|
||||
CmpInitHiveViewList((PCMHIVE)SystemHive);
|
||||
CmpInitSecurityCache((PCMHIVE)SystemHive);
|
||||
|
||||
/* Initialize the Hive */
|
||||
Status = HvInitialize(SystemHive,
|
||||
HINIT_MEMORY_INPLACE, /* FIXME: Should be flat */
|
||||
HIVE_VOLATILE,
|
||||
HFILE_TYPE_PRIMARY,
|
||||
(ULONG_PTR)SystemHiveData,
|
||||
1,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
|
||||
|
||||
/* Sanity check, flat hives don't have release routines */
|
||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||
|
||||
/* FIXME: Prepare it */
|
||||
CmPrepareHive(SystemHive);
|
||||
|
||||
/* Set the Root Cell */
|
||||
RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
|
||||
|
||||
/* Find the current control set */
|
||||
RtlInitUnicodeString(&KeyName, L"current");
|
||||
BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
|
||||
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
|
||||
|
||||
/* Find the control subkey */
|
||||
RtlInitUnicodeString(&KeyName, L"control");
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
|
||||
BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
|
||||
|
||||
/* Loop each key */
|
||||
while (ControlVector->KeyPath)
|
||||
{
|
||||
/* Assume failure */
|
||||
Length = -1;
|
||||
|
||||
/* Get the cell for this key */
|
||||
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
|
||||
if (KeyCell != HCELL_NIL)
|
||||
{
|
||||
/* Now get the cell for the value */
|
||||
RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
|
||||
ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||
if (ValueCell != HCELL_NIL)
|
||||
{
|
||||
/* Check if there's any data */
|
||||
if (!ControlVector->BufferLength)
|
||||
{
|
||||
/* No, the buffer will only be large enough for a ULONG */
|
||||
DataSize = sizeof(ULONG);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, save the data size */
|
||||
DataSize = *ControlVector->BufferLength;
|
||||
}
|
||||
|
||||
/* Get the actual data */
|
||||
ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
|
||||
|
||||
/* Check if this is a small key */
|
||||
IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
|
||||
|
||||
/* If the length is bigger then our buffer, normalize it */
|
||||
if (DataSize < Length) Length = DataSize;
|
||||
|
||||
/* Make sure we have some data */
|
||||
if (Length > 0)
|
||||
{
|
||||
/* Check if this was a small key */
|
||||
if (IsSmallKey)
|
||||
{
|
||||
/* The buffer is directly safe to read */
|
||||
Buffer = (PVOID)(&(ValueData->Data));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the longer path */
|
||||
Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
|
||||
}
|
||||
|
||||
/* Sanity check if this is a small key */
|
||||
ASSERT((IsSmallKey ?
|
||||
(Length <= CM_KEY_VALUE_SMALL) : TRUE));
|
||||
|
||||
/* Copy the data in the buffer */
|
||||
RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
|
||||
}
|
||||
|
||||
/* Check if we should return the data type */
|
||||
if (ControlVector->Type)
|
||||
{
|
||||
/* Return the type that we read */
|
||||
*ControlVector->Type = ValueData->Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the size that we read */
|
||||
if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
|
||||
|
||||
/* Go to the next entry */
|
||||
ControlVector++;
|
||||
}
|
||||
|
||||
/* Check if the ID is in the registry */
|
||||
if (CmDefaultLanguageIdType == REG_SZ)
|
||||
{
|
||||
/* Read it */
|
||||
PsDefaultSystemLocaleId =
|
||||
(LCID)CmpConvertLangId(CmDefaultLanguageId,
|
||||
CmDefaultLanguageIdLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use EN_US by default */
|
||||
PsDefaultSystemLocaleId = 0x409;
|
||||
}
|
||||
|
||||
/* Check if the ID Is in the registry */
|
||||
if (CmInstallUILanguageIdType == REG_SZ)
|
||||
{
|
||||
/* Read it */
|
||||
PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
|
||||
CmInstallUILanguageIdLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, use the default */
|
||||
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
|
||||
}
|
||||
|
||||
/* Set the defaults for the Thread UI */
|
||||
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
|
||||
PsDefaultUILanguageId = PsInstallUILanguageId;
|
||||
}
|
718
reactos/ntoskrnl/config/cmdata.c
Normal file
718
reactos/ntoskrnl/config/cmdata.c
Normal file
|
@ -0,0 +1,718 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmdata.c
|
||||
* PURPOSE: Configuration Manager - Global Configuration Data
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
ULONG DummyData;
|
||||
ULONG CmNtGlobalFlag;
|
||||
ULONG CmNtCSDVersion;
|
||||
|
||||
WCHAR CmDefaultLanguageId[12];
|
||||
ULONG CmDefaultLanguageIdLength = sizeof(CmDefaultLanguageId);
|
||||
ULONG CmDefaultLanguageIdType;
|
||||
|
||||
WCHAR CmInstallUILanguageId[12];
|
||||
ULONG CmInstallUILanguageIdLength = sizeof(CmInstallUILanguageId);
|
||||
ULONG CmInstallUILanguageIdType;
|
||||
|
||||
WCHAR CmSuiteBuffer[128];
|
||||
ULONG CmSuiteBufferLength = sizeof(CmSuiteBuffer);
|
||||
ULONG CmSuiteBufferType;
|
||||
|
||||
CMHIVE CmControlHive;
|
||||
|
||||
CM_SYSTEM_CONTROL_VECTOR CmControlVector[] =
|
||||
{
|
||||
{
|
||||
L"Session Manager",
|
||||
L"ProtectionMode",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"ObjectSecurityMode",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"LUIDDeviceMapsDisabled",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"LSA",
|
||||
L"AuditBaseDirectories",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"LSA",
|
||||
L"AuditBaseObjects",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"LSA\\audit",
|
||||
L"ProcessAccessesToAudit",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"TimeZoneInformation",
|
||||
L"ActiveTimeBias",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"TimeZoneInformation",
|
||||
L"Bias",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"TimeZoneInformation",
|
||||
L"RealTimeIsUniversal",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"GlobalFlag",
|
||||
&CmNtGlobalFlag,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PagedPoolQuota",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"NonPagedPoolQuota",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PagingFileQuota",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"AllocationPreference",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"DynamicMemory",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"Mirroring",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"Mirroring",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SystemViewSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SessionViewSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SessionImageSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SessionPoolSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PoolUsageMaximum",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"MapAllocationFragment",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PagedPoolSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"NonPagedPoolSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"NonPagedPoolMaximumPercent",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"LargeSystemCache",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"LargeStackSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SystemPages",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"LowMemoryThreshold",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"HighMemoryThreshold",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"DisablePagingExecutive",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"ModifiedPageLife",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SecondLevelDataCache",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"ClearPageFileAtShutdown",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PoolTagSmallTableSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PoolTagBigTableSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PoolTag",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"PoolTagOverruns",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"SnapUnloads",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"ProtectNonPagedPool",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"TrackLockedPages",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"TrackPtes",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"VerifyDrivers",
|
||||
&DummyData,
|
||||
&DummyData,
|
||||
&DummyData
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"VerifyDriverLevel",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"VerifyMode",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"LargePageMinimum",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"EnforceWriteProtection",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"MakeLowMemory",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Memory Management",
|
||||
L"WriteWatch",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Executive",
|
||||
L"AdditionalCriticalWorkerThreads",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Executive",
|
||||
L"AdditionalDelayedWorkerThreads",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Executive",
|
||||
L"PriorityQuantumMatrix",
|
||||
&DummyData,
|
||||
&DummyData,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Kernel",
|
||||
L"DpcQueueDepth",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Kernel",
|
||||
L"MinimumDpcRate",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Kernel",
|
||||
L"AdjustDpcThreshold",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Kernel",
|
||||
L"IdealDpcRate",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\I/O System",
|
||||
L"CountOperations",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\I/O System",
|
||||
L"LargeIrpStackLocations",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\I/O System",
|
||||
L"IoVerifierLevel",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"ResourceTimeoutCount",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"CriticalSectionTimeout",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"HeapSegmentReserve",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"HeapSegmentCommit",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"HeapDeCommitTotalFreeThreshold",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"HeapDeCommitFreeBlockThreshold",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"ProductOptions",
|
||||
L"ProductType",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Terminal Server",
|
||||
L"TSEnabled",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Terminal Server",
|
||||
L"TSAppCompat",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
L"ProductOptions",
|
||||
L"ProductSuite",
|
||||
CmSuiteBuffer,
|
||||
&CmSuiteBufferLength,
|
||||
&CmSuiteBufferType
|
||||
},
|
||||
|
||||
{
|
||||
L"Windows",
|
||||
L"CSDVersion",
|
||||
&CmNtCSDVersion,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Nls\\Language",
|
||||
L"Default",
|
||||
CmDefaultLanguageId,
|
||||
&CmDefaultLanguageIdLength,
|
||||
&CmDefaultLanguageIdType
|
||||
},
|
||||
|
||||
{
|
||||
L"Nls\\Language",
|
||||
L"InstallLanguage",
|
||||
CmInstallUILanguageId,
|
||||
&CmInstallUILanguageIdLength,
|
||||
&CmInstallUILanguageIdType
|
||||
},
|
||||
|
||||
{
|
||||
L"\0\0",
|
||||
L"RegistrySizeLimit",
|
||||
&DummyData,
|
||||
&DummyData,
|
||||
&DummyData
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"ForceNpxEmulation",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"PowerPolicySimulate",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager\\Executive",
|
||||
L"MaxTimeSeparationBeforeCorrect",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Windows",
|
||||
L"ShutdownTime",
|
||||
&DummyData,
|
||||
&DummyData,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"PriorityControl",
|
||||
L"Win32PrioritySeparation",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"EnableTimerWatchdog",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"Session Manager",
|
||||
L"Debugger Retries",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"WMI",
|
||||
L"MaxEventSize",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"WMI\\Trace",
|
||||
L"UsePerformanceClock",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
L"WMI\\Trace",
|
||||
L"TraceAlignment",
|
||||
&DummyData,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
646
reactos/ntoskrnl/config/cmindex.c
Normal file
646
reactos/ntoskrnl/config/cmindex.c
Normal file
|
@ -0,0 +1,646 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmindex.c
|
||||
* PURPOSE: Configuration Manager - Cell Indexes
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
CmpDoCompareKeyName(IN PHHIVE Hive,
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN HCELL_INDEX Cell)
|
||||
{
|
||||
PCM_KEY_NODE Node;
|
||||
UNICODE_STRING KeyName;
|
||||
LONG Result;
|
||||
|
||||
/* Get the node */
|
||||
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if (!Node) return 2;
|
||||
|
||||
/* Check if it's compressed */
|
||||
if (Node->Flags & KEY_COMP_NAME)
|
||||
{
|
||||
/* Compare compressed names */
|
||||
Result = CmpCompareCompressedName(SearchName,
|
||||
Node->Name,
|
||||
Node->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compare the Unicode name directly */
|
||||
KeyName.Buffer = Node->Name;
|
||||
KeyName.Length = Node->NameLength;
|
||||
KeyName.MaximumLength = KeyName.Length;
|
||||
Result = RtlCompareUnicodeString(SearchName, &KeyName, TRUE);
|
||||
}
|
||||
|
||||
/* Release the cell and return the normalized result */
|
||||
HvReleaseCell(Hive, Cell);
|
||||
return (Result == 0) ? Result : ((Result > 0) ? 1 : -1);
|
||||
}
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
CmpCompareInIndex(IN PHHIVE Hive,
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN ULONG Count,
|
||||
IN PCM_KEY_INDEX Index,
|
||||
IN PHCELL_INDEX SubKey)
|
||||
{
|
||||
PCM_KEY_FAST_INDEX FastIndex;
|
||||
PCM_INDEX FastEntry;
|
||||
LONG Result;
|
||||
ULONG i;
|
||||
ULONG ActualNameLength = 4, CompareLength, NameLength;
|
||||
WCHAR p, pp;
|
||||
|
||||
/* Assume failure */
|
||||
*SubKey = HCELL_NIL;
|
||||
|
||||
/* Check if we are a fast or hashed leaf */
|
||||
if ((Index->Signature == CM_KEY_FAST_LEAF) ||
|
||||
(Index->Signature == CM_KEY_HASH_LEAF))
|
||||
{
|
||||
/* Get the Fast/Hash Index */
|
||||
FastIndex = (PCM_KEY_FAST_INDEX)Index;
|
||||
FastEntry = &FastIndex->List[Count];
|
||||
|
||||
/* Check if we are a hash leaf, in which case we skip all this */
|
||||
if (Index->Signature == CM_KEY_FAST_LEAF)
|
||||
{
|
||||
/* Find out just how much of the name is there */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* Check if this entry is empty */
|
||||
if (!FastEntry->NameHint[i])
|
||||
{
|
||||
/* Only this much! */
|
||||
ActualNameLength = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* How large is the name and how many characters to compare */
|
||||
NameLength = SearchName->Length / sizeof(WCHAR);
|
||||
CompareLength = min(NameLength, ActualNameLength);
|
||||
|
||||
/* Loop all the chars we'll test */
|
||||
for (i = 0; i < CompareLength; i++)
|
||||
{
|
||||
/* Get one char from each buffer */
|
||||
p = SearchName->Buffer[i];
|
||||
pp = FastEntry->NameHint[i];
|
||||
|
||||
/* See if they match and return result if they don't */
|
||||
Result = (LONG)RtlUpcaseUnicodeChar(p) -
|
||||
(LONG)RtlUpcaseUnicodeChar(pp);
|
||||
if (Result) return (Result > 0) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here then we have to do a full compare */
|
||||
Result = CmpDoCompareKeyName(Hive, SearchName, FastEntry->Cell);
|
||||
if (Result == 2) return Result;
|
||||
if (!Result) *SubKey = FastEntry->Cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We aren't, so do a name compare and return the subkey found */
|
||||
Result = CmpDoCompareKeyName(Hive, SearchName, Index->List[Count]);
|
||||
if (Result == 2) return Result;
|
||||
if (!Result) *SubKey = Index->List[Count];
|
||||
}
|
||||
|
||||
/* Return the comparison result */
|
||||
return Result;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
CmpFindSubKeyInRoot(IN PHHIVE Hive,
|
||||
IN PCM_KEY_INDEX Index,
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN PHCELL_INDEX SubKey)
|
||||
{
|
||||
ULONG High, Low = 0, i, ReturnIndex;
|
||||
HCELL_INDEX LeafCell;
|
||||
PCM_KEY_INDEX Leaf;
|
||||
LONG Result;
|
||||
|
||||
/* Verify Index for validity */
|
||||
ASSERTMSG("We don't do a linear search yet!\n", FALSE);
|
||||
ASSERT(Index->Count != 0);
|
||||
ASSERT(Index->Signature == CM_KEY_INDEX_ROOT);
|
||||
|
||||
/* Set high limit and loop */
|
||||
High = Index->Count - 1;
|
||||
while (TRUE)
|
||||
{
|
||||
/* Choose next entry */
|
||||
i = ((High - Low) / 2) + Low;
|
||||
|
||||
/* Get the leaf cell and then the leaf itself */
|
||||
LeafCell = Index->List[i];
|
||||
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||
if (Leaf)
|
||||
{
|
||||
/* Make sure the leaf is valid */
|
||||
ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
|
||||
(Leaf->Signature == CM_KEY_FAST_LEAF) ||
|
||||
(Leaf->Signature == CM_KEY_HASH_LEAF));
|
||||
ASSERT(Leaf->Count != 0);
|
||||
|
||||
/* Do the compare */
|
||||
Result = CmpCompareInIndex(Hive,
|
||||
SearchName,
|
||||
Leaf->Count - 1,
|
||||
Leaf,
|
||||
SubKey);
|
||||
if (Result == 2) goto Big;
|
||||
|
||||
/* Check if we found the leaf */
|
||||
if (!Result)
|
||||
{
|
||||
/* We found the leaf */
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = i;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* Check for negative result */
|
||||
if (Result < 0)
|
||||
{
|
||||
/* If we got here, we should be at -1 */
|
||||
ASSERT(Result == -1);
|
||||
|
||||
/* Do another lookup, since we might still be in the right leaf */
|
||||
Result = CmpCompareInIndex(Hive,
|
||||
SearchName,
|
||||
0,
|
||||
Leaf,
|
||||
SubKey);
|
||||
if (Result == 2) goto Big;
|
||||
|
||||
/* Check if it's not below */
|
||||
if (Result >= 0)
|
||||
{
|
||||
/*
|
||||
* If the name was first below, and now it is above,
|
||||
* then this means that it is somewhere in this leaf.
|
||||
* Make sure we didn't get some weird result
|
||||
*/
|
||||
ASSERT((Result == 1) || (Result == 0));
|
||||
|
||||
/* Return it */
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = Low;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* Update the limit to this index, since we know it's not higher. */
|
||||
High = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the base to this index, since we know it's not lower. */
|
||||
Low = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Big:
|
||||
/* This was some sort of special key */
|
||||
ReturnIndex = 0x80000000;
|
||||
goto ReturnFailure;
|
||||
}
|
||||
|
||||
/* Check if there is only one entry left */
|
||||
if ((High - Low) <= 1) break;
|
||||
|
||||
/* Release the leaf cell */
|
||||
HvReleaseCell(Hive, LeafCell);
|
||||
}
|
||||
|
||||
/* Make sure we got here for the right reasons */
|
||||
ASSERT((High - Low == 1) || (High == Low));
|
||||
|
||||
/* Get the leaf cell and the leaf */
|
||||
LeafCell = Index->List[Low];
|
||||
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||
if (!Leaf) goto Big;
|
||||
|
||||
/* Do the compare */
|
||||
Result = CmpCompareInIndex(Hive,
|
||||
SearchName,
|
||||
Leaf->Count-1,
|
||||
Leaf,
|
||||
SubKey);
|
||||
if (Result == 2) goto Big;
|
||||
|
||||
/* Check if we found it */
|
||||
if (!Result)
|
||||
{
|
||||
/* We got lucky...return it */
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = Low;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* It's below, so could still be in this leaf */
|
||||
if (Result < 0)
|
||||
{
|
||||
/* Make sure we're -1 */
|
||||
ASSERT(Result == -1);
|
||||
|
||||
/* Do a search from the bottom */
|
||||
Result = CmpCompareInIndex(Hive, SearchName, 0, Leaf, SubKey);
|
||||
if (Result == 2) goto Big;
|
||||
|
||||
/*
|
||||
* Check if it's above, which means that it's within the ranges of our
|
||||
* leaf (since we were below before).
|
||||
*/
|
||||
if (Result >= 0)
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT((Result == 1) || (Result == 0));
|
||||
|
||||
/* Yep, so we're in the right leaf; return it. */
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = Low;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* It's still below us, so fail */
|
||||
ReturnIndex = Low;
|
||||
goto ReturnFailure;
|
||||
}
|
||||
|
||||
/* Release the leaf cell */
|
||||
HvReleaseCell(Hive, LeafCell);
|
||||
|
||||
/* Well the low didn't work too well, so try the high. */
|
||||
LeafCell = Index->List[High];
|
||||
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||
if (!Leaf) goto Big;
|
||||
|
||||
/* Do the compare */
|
||||
Result = CmpCompareInIndex(Hive,
|
||||
SearchName,
|
||||
Leaf->Count - 1,
|
||||
Leaf,
|
||||
SubKey);
|
||||
if (Result == 2) goto Big;
|
||||
|
||||
/* Check if we found it */
|
||||
if (Result == 0)
|
||||
{
|
||||
/* We got lucky... return it */
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = High;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* Check if we are too high */
|
||||
if (Result < 0)
|
||||
{
|
||||
/* Make sure we're -1 */
|
||||
ASSERT(Result == -1);
|
||||
|
||||
/*
|
||||
* Once again... since we were first too low and now too high, then
|
||||
* this means we are within the range of this leaf... return it.
|
||||
*/
|
||||
*SubKey = LeafCell;
|
||||
ReturnIndex = High;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* If we got here, then we are too low, again. */
|
||||
ReturnIndex = High;
|
||||
|
||||
/* Failure path */
|
||||
ReturnFailure:
|
||||
*SubKey = HCELL_NIL;
|
||||
|
||||
/* Return path...check if we have a leaf to free */
|
||||
Return:
|
||||
if (Leaf) HvReleaseCell(Hive, LeafCell);
|
||||
|
||||
/* Return the index */
|
||||
return ReturnIndex;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
CmpFindSubKeyInLeaf(IN PHHIVE Hive,
|
||||
IN PCM_KEY_INDEX Index,
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN PHCELL_INDEX SubKey)
|
||||
{
|
||||
ULONG High, Low = 0, i;
|
||||
LONG Result;
|
||||
|
||||
/* Verify Index for validity */
|
||||
ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
|
||||
(Index->Signature == CM_KEY_FAST_LEAF) ||
|
||||
(Index->Signature == CM_KEY_HASH_LEAF));
|
||||
|
||||
/* Get the upper bound and middle entry */
|
||||
High = Index->Count - 1;
|
||||
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
|
||||
i = High / 2;
|
||||
#else
|
||||
i = 0;
|
||||
#endif
|
||||
|
||||
/* Check if we don't actually have any entries */
|
||||
if (!Index->Count)
|
||||
{
|
||||
/* Return failure */
|
||||
*SubKey = HCELL_NIL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start compare loop */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Do the actual comparison and check the result */
|
||||
Result = CmpCompareInIndex(Hive, SearchName, i, Index, SubKey);
|
||||
if (Result == 2)
|
||||
{
|
||||
/* Fail with special value */
|
||||
*SubKey = HCELL_NIL;
|
||||
return 0x80000000;
|
||||
}
|
||||
|
||||
/* Check if we got lucky and found it */
|
||||
if (!Result) return i;
|
||||
|
||||
/* Check if the result is below us */
|
||||
if (Result < 0)
|
||||
{
|
||||
/* Set the new bound; it can't be higher then where we are now. */
|
||||
ASSERT(Result == -1);
|
||||
High = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new bound... it can't be lower then where we are now. */
|
||||
ASSERT(Result == 1);
|
||||
Low = i;
|
||||
}
|
||||
|
||||
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
|
||||
/* Check if this is the last entry, if so, break out and handle it */
|
||||
if ((High - Low) <= 1) break;
|
||||
|
||||
/* Set the new index */
|
||||
i = ((High - Low) / 2) + Low;
|
||||
#else
|
||||
if (++i > High)
|
||||
{
|
||||
/* Return failure */
|
||||
*SubKey = HCELL_NIL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here, High - Low = 1 or High == Low
|
||||
* Simply look first at Low, then at High
|
||||
*/
|
||||
Result = CmpCompareInIndex(Hive, SearchName, Low, Index, SubKey);
|
||||
if (Result == 2)
|
||||
{
|
||||
/* Fail with special value */
|
||||
*SubKey = HCELL_NIL;
|
||||
return 0x80000000;
|
||||
}
|
||||
|
||||
/* Check if we got lucky and found it */
|
||||
if (!Result) return Low;
|
||||
|
||||
/* Check if the result is below us */
|
||||
if (Result < 0)
|
||||
{
|
||||
/* Return the low entry */
|
||||
ASSERT(Result == -1);
|
||||
return Low;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got here, then just check the high and return it no matter what
|
||||
* the result is (since we're a leaf, it has to be near there anyway).
|
||||
*/
|
||||
Result = CmpCompareInIndex(Hive, SearchName, High, Index, SubKey);
|
||||
if (Result == 2)
|
||||
{
|
||||
/* Fail with special value */
|
||||
*SubKey = HCELL_NIL;
|
||||
return 0x80000000;
|
||||
}
|
||||
|
||||
/* Return the high */
|
||||
return High;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
CmpComputeHashKey(IN ULONG Hash,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN BOOLEAN AllowSeparators)
|
||||
{
|
||||
LPWSTR Cp;
|
||||
ULONG Value, i;
|
||||
|
||||
/* Make some sanity checks on our parameters */
|
||||
ASSERT((Name->Length == 0) ||
|
||||
(AllowSeparators) ||
|
||||
(Name->Buffer[0] != OBJ_NAME_PATH_SEPARATOR));
|
||||
|
||||
/* If the name is empty, there is nothing to hash! */
|
||||
if (!Name->Length) return Hash;
|
||||
|
||||
/* Set the buffer and loop every character */
|
||||
Cp = Name->Buffer;
|
||||
for (i = 0; i < Name->Length; i += sizeof(WCHAR), Cp++)
|
||||
{
|
||||
/* Make sure we don't have a separator when we shouldn't */
|
||||
ASSERT(AllowSeparators || (*Cp != OBJ_NAME_PATH_SEPARATOR));
|
||||
|
||||
/* Check what kind of char we have */
|
||||
if (*Cp >= L'a')
|
||||
{
|
||||
/* In the lower case region... is it truly lower case? */
|
||||
if (*Cp < L'z')
|
||||
{
|
||||
/* Yes! Calculate it ourselves! */
|
||||
Value = *Cp - L'a' + L'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No, use the API */
|
||||
Value = RtlUpcaseUnicodeChar(*Cp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reuse the char, it's already upcased */
|
||||
Value = *Cp;
|
||||
}
|
||||
|
||||
/* Multiply by a prime and add our value */
|
||||
Hash *= 37;
|
||||
Hash += Value;
|
||||
}
|
||||
|
||||
/* Return the hash */
|
||||
return Hash;
|
||||
}
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindSubKeyByHash(IN PHHIVE Hive,
|
||||
IN PCM_KEY_FAST_INDEX FastIndex,
|
||||
IN PUNICODE_STRING SearchName)
|
||||
{
|
||||
ULONG HashKey, i;
|
||||
PCM_INDEX FastEntry;
|
||||
|
||||
/* Make sure it's really a hash */
|
||||
ASSERT(FastIndex->Signature == CM_KEY_HASH_LEAF);
|
||||
|
||||
/* Compute the hash key for the name */
|
||||
HashKey = CmpComputeHashKey(0, SearchName, FALSE);
|
||||
|
||||
/* Loop all the entries */
|
||||
for (i = 0; i < FastIndex->Count; i++)
|
||||
{
|
||||
/* Get the entry */
|
||||
FastEntry = &FastIndex->List[i];
|
||||
|
||||
/* Compare the hash first */
|
||||
if (FastEntry->HashKey == HashKey)
|
||||
{
|
||||
/* Go ahead for a full compare */
|
||||
if (!(CmpDoCompareKeyName(Hive, SearchName, FastEntry->Cell)))
|
||||
{
|
||||
/* It matched, return the cell */
|
||||
return FastEntry->Cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here then we failed */
|
||||
return HCELL_NIL;
|
||||
}
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindSubKeyByName(IN PHHIVE Hive,
|
||||
IN PCM_KEY_NODE Parent,
|
||||
IN PUNICODE_STRING SearchName)
|
||||
{
|
||||
ULONG i;
|
||||
PCM_KEY_INDEX IndexRoot;
|
||||
HCELL_INDEX SubKey, CellToRelease;
|
||||
ULONG Found;
|
||||
|
||||
/* Loop each storage type */
|
||||
for (i = 0; i < Hive->StorageTypeCount; i++)
|
||||
{
|
||||
/* Make sure the parent node has subkeys */
|
||||
if (Parent->SubKeyCounts[i])
|
||||
{
|
||||
/* Get the Index */
|
||||
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
|
||||
#if 0
|
||||
/* Make sure we have one and that the cell is allocated */
|
||||
ASSERT((IndexRoot == NULL) ||
|
||||
HvIsCellAllocated(Hive, Parent->SubKeyLists[i]));
|
||||
#endif
|
||||
/* Fail if we don't actually have an index root */
|
||||
if (!IndexRoot) return HCELL_NIL;
|
||||
|
||||
/* Get the cell we'll need to release */
|
||||
CellToRelease = Parent->SubKeyLists[i];
|
||||
|
||||
/* Check if this is another index root */
|
||||
if (IndexRoot->Signature == CM_KEY_INDEX_ROOT)
|
||||
{
|
||||
/* Lookup the name in the root */
|
||||
Found = CmpFindSubKeyInRoot(Hive,
|
||||
IndexRoot,
|
||||
SearchName,
|
||||
&SubKey);
|
||||
|
||||
/* Release the previous cell */
|
||||
ASSERT(CellToRelease != HCELL_NIL);
|
||||
HvReleaseCell(Hive, CellToRelease);
|
||||
|
||||
/* Make sure we found something valid */
|
||||
if (Found < 0) break;
|
||||
|
||||
/* Get the new Index Root and set the new cell to be released */
|
||||
if (SubKey == HCELL_NIL) continue;
|
||||
CellToRelease = SubKey;
|
||||
IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, SubKey);
|
||||
}
|
||||
|
||||
/* Make sure the signature is what we expect it to be */
|
||||
ASSERT((IndexRoot->Signature == CM_KEY_INDEX_LEAF) ||
|
||||
(IndexRoot->Signature == CM_KEY_FAST_LEAF) ||
|
||||
(IndexRoot->Signature == CM_KEY_HASH_LEAF));
|
||||
|
||||
/* Check if this isn't a hashed leaf */
|
||||
if (IndexRoot->Signature != CM_KEY_HASH_LEAF)
|
||||
{
|
||||
/* Find the subkey in the leaf */
|
||||
Found = CmpFindSubKeyInLeaf(Hive,
|
||||
IndexRoot,
|
||||
SearchName,
|
||||
&SubKey);
|
||||
|
||||
/* Release the previous cell */
|
||||
ASSERT(CellToRelease != HCELL_NIL);
|
||||
HvReleaseCell(Hive, CellToRelease);
|
||||
|
||||
/* Make sure we found a valid index */
|
||||
if (Found < 0) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find the subkey in the hash */
|
||||
SubKey = CmpFindSubKeyByHash(Hive,
|
||||
(PCM_KEY_FAST_INDEX)IndexRoot,
|
||||
SearchName);
|
||||
|
||||
/* Release the previous cell */
|
||||
ASSERT(CellToRelease != HCELL_NIL);
|
||||
HvReleaseCell(Hive, CellToRelease);
|
||||
}
|
||||
|
||||
/* Make sure we got a valid subkey and return it */
|
||||
if (SubKey != HCELL_NIL) return SubKey;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here, then we failed */
|
||||
return HCELL_NIL;
|
||||
}
|
33
reactos/ntoskrnl/config/cmmapvw.c
Normal file
33
reactos/ntoskrnl/config/cmmapvw.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmmapvw.c
|
||||
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitHiveViewList(IN PCMHIVE Hive)
|
||||
{
|
||||
/* Initialize the list heads */
|
||||
InitializeListHead(&Hive->LRUViewListHead);
|
||||
InitializeListHead(&Hive->PinViewListHead);
|
||||
|
||||
/* Reset data */
|
||||
Hive->MappedViews = 0;
|
||||
Hive->PinnedViews = 0;
|
||||
Hive->UseCount = 0;
|
||||
}
|
||||
|
166
reactos/ntoskrnl/config/cmname.c
Normal file
166
reactos/ntoskrnl/config/cmname.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmname.c
|
||||
* PURPOSE: Configuration Manager - Name Management
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
CmpCompareCompressedName(IN PUNICODE_STRING SearchName,
|
||||
IN PWCHAR CompressedName,
|
||||
IN ULONG NameLength)
|
||||
{
|
||||
WCHAR *p;
|
||||
CHAR *pp;
|
||||
WCHAR p1, p2;
|
||||
USHORT SearchLength;
|
||||
LONG Result;
|
||||
|
||||
/* Set the pointers and length and then loop */
|
||||
p = SearchName->Buffer;
|
||||
pp = (PCHAR)CompressedName;
|
||||
SearchLength = (SearchName->Length / sizeof(WCHAR));
|
||||
while ((SearchLength) && (NameLength))
|
||||
{
|
||||
/* Get the characters */
|
||||
p1 = *p++;
|
||||
p2 = (WCHAR)(*pp++);
|
||||
|
||||
/* Check if we have a direct match */
|
||||
if (p1 != p2)
|
||||
{
|
||||
/* See if they match and return result if they don't */
|
||||
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
|
||||
(LONG)RtlUpcaseUnicodeChar(p2);
|
||||
if (Result) return Result;
|
||||
}
|
||||
|
||||
/* Next chars */
|
||||
SearchLength--;
|
||||
NameLength--;
|
||||
}
|
||||
|
||||
/* Return the difference directly */
|
||||
return SearchLength - NameLength;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpFindNameInList(IN PHHIVE Hive,
|
||||
IN PCHILD_LIST ChildList,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN PULONG ChildIndex,
|
||||
IN PHCELL_INDEX CellIndex)
|
||||
{
|
||||
PCELL_DATA CellData;
|
||||
HCELL_INDEX CellToRelease = HCELL_NIL;
|
||||
ULONG i;
|
||||
PCM_KEY_VALUE KeyValue;
|
||||
LONG Result;
|
||||
UNICODE_STRING SearchName;
|
||||
BOOLEAN Success;
|
||||
|
||||
/* Make sure there's actually something on the list */
|
||||
if (ChildList->Count != 0)
|
||||
{
|
||||
/* Get the cell data */
|
||||
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
|
||||
if (!CellData)
|
||||
{
|
||||
/* Couldn't get the cell... tell the caller */
|
||||
*CellIndex = HCELL_NIL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now loop every entry */
|
||||
for (i = 0; i < ChildList->Count; i++)
|
||||
{
|
||||
/* Check if we have a cell to release */
|
||||
if (CellToRelease != HCELL_NIL)
|
||||
{
|
||||
/* Release it */
|
||||
HvReleaseCell(Hive, CellToRelease);
|
||||
CellToRelease = HCELL_NIL;
|
||||
}
|
||||
|
||||
/* Get this value */
|
||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
|
||||
if (!KeyValue)
|
||||
{
|
||||
/* Return with no data found */
|
||||
*CellIndex = HCELL_NIL;
|
||||
Success = FALSE;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* Save the cell to release */
|
||||
CellToRelease = CellData->u.KeyList[i];
|
||||
|
||||
/* Check if it's a compressed value name */
|
||||
if (KeyValue->Flags & VALUE_COMP_NAME)
|
||||
{
|
||||
/* Use the compressed name check */
|
||||
Result = CmpCompareCompressedName(Name,
|
||||
KeyValue->Name,
|
||||
KeyValue->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setup the Unicode string */
|
||||
SearchName.Length = KeyValue->NameLength;
|
||||
SearchName.MaximumLength = SearchName.Length;
|
||||
SearchName.Buffer = KeyValue->Name;
|
||||
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
|
||||
}
|
||||
|
||||
/* Check if we found it */
|
||||
if (!Result)
|
||||
{
|
||||
/* We did...return info to caller */
|
||||
if (ChildIndex) *ChildIndex = i;
|
||||
*CellIndex = CellData->u.KeyList[i];
|
||||
|
||||
/* Set success state */
|
||||
Success = TRUE;
|
||||
goto Return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Got to the end of the list */
|
||||
if (ChildIndex) *ChildIndex = i;
|
||||
*CellIndex = HCELL_NIL;
|
||||
|
||||
/* Nothing found if we got here */
|
||||
Success = TRUE;
|
||||
goto Return;
|
||||
}
|
||||
|
||||
/* Nothing found...check if the caller wanted more info */
|
||||
ASSERT(ChildList->Count == 0);
|
||||
if (ChildIndex) *ChildIndex = 0;
|
||||
*CellIndex = HCELL_NIL;
|
||||
|
||||
/* Nothing found if we got here */
|
||||
return TRUE;
|
||||
|
||||
Return:
|
||||
/* Release the first cell we got */
|
||||
if (CellData) HvReleaseCell(Hive, ChildList->List);
|
||||
|
||||
/* Release the secondary one, if we have one */
|
||||
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
|
||||
return Success;
|
||||
}
|
75
reactos/ntoskrnl/config/cmparse.c
Normal file
75
reactos/ntoskrnl/config/cmparse.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmparse.c
|
||||
* PURPOSE: Configuration Manager - Object Manager Parse Interface
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpGetNextName(IN OUT PUNICODE_STRING RemainingName,
|
||||
OUT PUNICODE_STRING NextName,
|
||||
OUT PBOOLEAN LastName)
|
||||
{
|
||||
BOOLEAN NameValid = TRUE;
|
||||
|
||||
/* Check if there's nothing left in the name */
|
||||
if (!(RemainingName->Buffer) ||
|
||||
(!RemainingName->Length) ||
|
||||
!(*RemainingName->Buffer))
|
||||
{
|
||||
/* Clear the next name and set this as last */
|
||||
*LastName = TRUE;
|
||||
NextName->Buffer = NULL;
|
||||
NextName->Length = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check if we have a path separator */
|
||||
if (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
/* Skip it */
|
||||
RemainingName->Buffer++;
|
||||
RemainingName->Length -= sizeof(WCHAR);
|
||||
RemainingName->MaximumLength -= sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* Start loop at where the current buffer is */
|
||||
NextName->Buffer = RemainingName->Buffer;
|
||||
while (TRUE)
|
||||
{
|
||||
/* Break out if we ran out or hit a path separator */
|
||||
if (!(RemainingName->Length) ||
|
||||
(*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to the next character */
|
||||
RemainingName->Buffer++;
|
||||
RemainingName->Length -= sizeof(WCHAR);
|
||||
RemainingName->MaximumLength -= sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* See how many chars we parsed and validate the length */
|
||||
NextName->Length = (USHORT)((ULONG_PTR)RemainingName->Buffer -
|
||||
(ULONG_PTR)NextName->Buffer);
|
||||
if (NextName->Length > 512) NameValid = FALSE;
|
||||
NextName->MaximumLength = NextName->Length;
|
||||
|
||||
/* If there's nothing left, we're last */
|
||||
*LastName = !RemainingName->Length;
|
||||
return NameValid;
|
||||
}
|
38
reactos/ntoskrnl/config/cmsecach.c
Normal file
38
reactos/ntoskrnl/config/cmsecach.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmsecach.c
|
||||
* PURPOSE: Configuration Manager - Security Cache
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpInitSecurityCache(IN PCMHIVE Hive)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
/* Reset data */
|
||||
Hive->SecurityCount = 0;
|
||||
Hive->SecurityCacheSize = 0;
|
||||
Hive->SecurityHitHint = -1;
|
||||
Hive->SecurityCache = NULL;
|
||||
|
||||
/* Loop every security hash */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
/* Initialize it */
|
||||
InitializeListHead(&Hive->SecurityHash[i]);
|
||||
}
|
||||
}
|
125
reactos/ntoskrnl/config/cmvalue.c
Normal file
125
reactos/ntoskrnl/config/cmvalue.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/config/cmvalue.c
|
||||
* PURPOSE: Configuration Manager - Cell Values
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ntoskrnl.h"
|
||||
#include "cm.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindValueByName(IN PHHIVE Hive,
|
||||
IN PCM_KEY_NODE KeyNode,
|
||||
IN PUNICODE_STRING Name)
|
||||
{
|
||||
HCELL_INDEX CellIndex;
|
||||
|
||||
/* Call the main function */
|
||||
if (!CmpFindNameInList(Hive,
|
||||
&KeyNode->ValueList,
|
||||
Name,
|
||||
NULL,
|
||||
&CellIndex))
|
||||
{
|
||||
/* Santy check */
|
||||
ASSERT(CellIndex == HCELL_NIL);
|
||||
}
|
||||
|
||||
/* Return the index */
|
||||
return CellIndex;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpGetValueData(IN PHHIVE Hive,
|
||||
IN PCM_KEY_VALUE Value,
|
||||
IN PULONG Length,
|
||||
OUT PVOID *Buffer,
|
||||
OUT PBOOLEAN BufferAllocated,
|
||||
OUT PHCELL_INDEX CellToRelease)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
|
||||
|
||||
/* Set failure defaults */
|
||||
*BufferAllocated = FALSE;
|
||||
*Buffer = NULL;
|
||||
*CellToRelease = HCELL_NIL;
|
||||
|
||||
/* Check if this is a small key */
|
||||
if (CmpIsKeyValueSmall(Length, Value->DataLength))
|
||||
{
|
||||
/* Return the data immediately */
|
||||
*Buffer = &Value->Data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check if this is a big cell */
|
||||
if (CmpIsKeyValueBig(Hive, *Length))
|
||||
{
|
||||
/* FIXME: We don't support big cells */
|
||||
DPRINT1("Unsupported cell type!\n");
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* Get the data from the cell */
|
||||
*Buffer = HvGetCell(Hive, Value->Data);
|
||||
if (!(*Buffer)) return FALSE;
|
||||
|
||||
/* Return success and the cell to be released */
|
||||
*CellToRelease = Value->Data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PCELL_DATA
|
||||
NTAPI
|
||||
CmpValueToData(IN PHHIVE Hive,
|
||||
IN PCM_KEY_VALUE Value,
|
||||
OUT PULONG Length)
|
||||
{
|
||||
PCELL_DATA Buffer;
|
||||
BOOLEAN BufferAllocated;
|
||||
HCELL_INDEX CellToRelease;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(Hive->ReleaseCellRoutine == NULL);
|
||||
|
||||
/* Get the actual data */
|
||||
if (!CmpGetValueData(Hive,
|
||||
Value,
|
||||
Length,
|
||||
(PVOID)&Buffer,
|
||||
&BufferAllocated,
|
||||
&CellToRelease))
|
||||
{
|
||||
/* We failed */
|
||||
ASSERT(BufferAllocated == FALSE);
|
||||
ASSERT(Buffer == NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This should never happen!*/
|
||||
if (BufferAllocated)
|
||||
{
|
||||
/* Free the buffer and bugcheck */
|
||||
ExFreePool(Buffer);
|
||||
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
|
||||
}
|
||||
|
||||
/* Otherwise, return the cell data */
|
||||
return Buffer;
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue