test: cmp.h File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# cmp.h File Reference

`#include "ntos.h"`
`#include "hive.h"`
`#include "wchar.h"`
`#include "zwapi.h"`
`#include <stdio.h>`
`#include <profiles.h>`
`#include "cmdata.h"`

Go to the source code of this file.

## Classes

struct | _BOOT_DRIVER_NODE
struct | _CM_KEY_BODY
struct | _CM_POST_KEY_BODY
struct | _CM_NOTIFY_BLOCK
struct | _CM_SYNC_POST_BLOCK
struct | _CM_ASYNC_USER_POST_BLOCK
struct | _CM_ASYNC_KERNEL_POST_BLOCK
union | _CM_POST_BLOCK_UNION
struct | _CM_POST_BLOCK
struct | _CMHIVE
struct | _REGISTRY_COMMAND
struct | _CM_PARSE_CONTEXT
struct | _HIVE_LIST_ENTRY
struct | _CM_HARDWARE_PROFILE
struct | _CM_HARDWARE_PROFILE_LIST
struct | _CM_HARDWARE_PROFILE_ALIAS
struct | _CM_HARDWARE_PROFILE_ALIAS_LIST
struct | _CM_HARDWARE_PROFILE_ACPI_ALIAS
struct | _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST

## Defines

#define | _CM_ENTRYLIST_MANIPULATION
#define | CmpRemoveEntryList(a)
#define | CmpClearListEntry(a) (a)->Flink = (a)->Blink = NULL
#define | _WMI_TRACING_REGISTRYCALLS
#define | CmpWmiFireEvent(Status, KeyHandle, ElapsedTime, KeyName, Type)
#define | StartWmiCmTrace()
#define | EndWmiCmTrace(Status, Handle, KeyName, Type)
#define | CmpMakeSpecialPoolReadOnly(a)
#define | CmpMakeSpecialPoolReadWrite(a)
#define | CmpMakeValueCacheReadOnly(a, b)
#define | CmpMakeValueCacheReadWrite(a, b)
#define | HvpChangeBinAllocation(a, b)
#define | HvpMarkBinReadWrite(a, b)
#define | CmpMarkAllBinsReadOnly(a)
#define | CmpAllocateTag(a, b, c) CmpAllocate(a,b)
#define | CM_CACHE_FAKE_KEY 0x00000001
#define | LOCK_KCB_TREE() ExAcquireFastMutexUnsafe(&CmpKcbLock)
#define | UNLOCK_KCB_TREE() ExReleaseFastMutexUnsafe(&CmpKcbLock)
#define | CML_BUGCHECK 1
#define | CML_API 2
#define | CML_API_ARGS 3
#define | CML_WORKER 4
#define | CML_MAJOR 5
#define | CML_MINOR 6
#define | CML_FLOW 7
#define | CML_BIN 8
#define | CMS_MAP 0x00000001
#define | CMS_INIT 0x00000002
#define | CMS_NTAPI 0x00000004
#define | CMS_HIVE 0x00000008
#define | CMS_IO 0x00000010
#define | CMS_PARSE 0x00000020
#define | CMS_SAVRES 0x00000040
#define | CMS_CM 0x00000080
#define | CMS_SEC 0x00000100
#define | CMS_POOL 0x00000200
#define | CMS_LOCKING 0x00000400
#define | CMS_NOTIFY 0x00000800
#define | CMS_EXCEPTION 0x00001000
#define | CMS_INDEX 0x00002000
#define | CMS_BIN_MAP 0x00004000
#define | CMS_MAP_ERROR 0x00010000
#define | CMS_INIT_ERROR 0x00020000
#define | CMS_NTAPI_ERROR 0x00040000
#define | CMS_HIVE_ERROR 0x00080000
#define | CMS_IO_ERROR 0x00100000
#define | CMS_PARSE_ERROR 0x00200000
#define | CMS_SAVRES_ERROR 0x00400000
#define | CMS_CM_ERROR 0x00800000
#define | CMS_SEC_ERROR 0x01000000
#define | CMS_POOL_ERROR 0x02000000
#define | CMS_LOCKING_ERROR 0x04000000
#define | CMS_NOTIFY_ERROR 0x08000000
#define | CMS_INDEX_ERROR 0x10000000
#define | CMS_DEFAULT ((~(CMS_MAP)) & 0xffffffff)
#define | CMLOG(level, select) if (0) {}
#define | REGCHECKING 1
#define | DCmCheckRegistry(a)
#define | REGISTRY_LOCK_CHECKING
#define | BEGIN_LOCK_CHECKPOINT
#define | END_LOCK_CHECKPOINT
#define | ASSERT_CM_LOCK_OWNED()
#define | ASSERT_CM_LOCK_OWNED_EXCLUSIVE()
#define | ASSERT_PASSIVE_LEVEL()
#define | CM_BUGCHECK(Code, Parm1, Parm2, Parm3, Parm4) KeBugCheckEx( Code, Parm1, Parm2, Parm3, Parm4 )
#define | VALIDATE_CELL_MAP(LINE, Map, Hive, Address)
#define | CmpDumpSecurityDescriptor(x, y)
#define | CLONE_CONTROL_SET FALSE
#define | NUMBER_TYPES (MaximumType + 1)
#define | CM_WRAP_LIMIT 0x7fffffff
#define | CM_MAX_STASH 1024*1024
#define | CM_MAX_REASONABLE_VALUES 100
#define | MAX_HIVE_LAYERS 2
#define | RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */
#define | RNDM_PRIME 1000000007 /* prime number, also used for scrambling */
#define | HASH_KEY(_convkey_) ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)
#define | GET_HASH_INDEX(Key) HASH_KEY(Key) % CmpHashTableSize
#define | GET_HASH_ENTRY(Table, Key) Table[GET_HASH_INDEX(Key)]
#define | KEY_BODY_TYPE 0x6b793032
#define | INIT_KCB_KEYBODY_LIST(kcb)
#define | ASSERT_KEYBODY_LIST_EMPTY(kcb)
#define | ENLIST_KEYBODY_IN_KEYBODY_LIST(KeyBody)
#define | DELIST_KEYBODY_FROM_KEYBODY_LIST(KeyBody)
#define | ASSERT_KEY_OBJECT(x) ASSERT(((PCM_KEY_BODY)x)->Type == KEY_BODY_TYPE)
#define | ASSERT_NODE(x) ASSERT(((PCM_KEY_NODE)x)->Signature == CM_KEY_NODE_SIGNATURE)
#define | ASSERT_SECURITY(x) ASSERT(((PCM_KEY_SECURITY)x)->Signature == CM_KEY_SECURITY_SIGNATURE)
#define | REG_NOTIFY_POST_TYPE_MASK (0x0000FFFFL)
#define | REG_NOTIFY_MASTER_POST (0x00010000L)
#define | PostBlockType(_post_) ((POST_BLOCK_TYPE)( ((_post_)->NotifyType) & REG_NOTIFY_POST_TYPE_MASK ))
#define | IsMasterPostBlock(_post_) ( ((_post_)->NotifyType) & REG_NOTIFY_MASTER_POST )
#define | SetMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) |= REG_NOTIFY_MASTER_POST )
#define | ClearMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) &= ~REG_NOTIFY_MASTER_POST )
#define | LOCK_POST_LIST() ExAcquireFastMutexUnsafe(&CmpPostLock)
#define | UNLOCK_POST_LIST() ExReleaseFastMutexUnsafe(&CmpPostLock)
#define | CmLockHive(_hive_)
#define | CmUnlockHive(_hive_)
#define | CmpHKeyNameLen(Key)
#define | CmpNcbNameLen(Ncb)
#define | CmpHKeyNodeSize(Hive, KeyName) (FIELD_OFFSET(CM_KEY_NODE, Name) + CmpNameSize(Hive, KeyName))
#define | CmpValueNameLen(Value)
#define | CmpHKeyValueSize(Hive, ValueName) (FIELD_OFFSET(CM_KEY_VALUE, Name) + CmpNameSize(Hive, ValueName))
#define | REG_CMD_INIT 1
#define | REG_CMD_FLUSH_KEY 2
#define | REG_CMD_FILE_SET_SIZE 3
#define | REG_CMD_HIVE_OPEN 4
#define | REG_CMD_HIVE_CLOSE 5
#define | REG_CMD_SHUTDOWN 6
#define | REG_CMD_RENAME_HIVE 7
#define | REG_CMD_ADD_HIVE_LIST 8
#define | REG_CMD_REMOVE_HIVE_LIST 9
#define | REG_CMD_REFRESH_HIVE 10
#define | REG_CMD_HIVE_READ 11
#define | REG_OPTION_PREDEF_HANDLE (0x00000008L)
#define | REG_PREDEF_HANDLE_MASK (0x80000000L)
#define | KCB_WORKER_CONTINUE 0
#define | KCB_WORKER_DONE 1
#define | KCB_WORKER_DELETE 2
#define | CmpFindValueByName(h, k, n) CmpFindNameInList(h,&((k)->ValueList),n,NULL,NULL)
#define | CmpCopyTree(s, c, t, l) CmpCopySyncTree(s,c,t,l,FALSE,Copy)
#define | CmpCopyTreeEx(s, c, t, l, f) CmpCopySyncTree(s,c,t,l,f,Copy)
#define | CmpSyncTrees(s, c, t, l, f) CmpCopySyncTree(s,c,t,l,f,Sync)
#define | CmpMergeTrees(s, c, t, l) CmpCopySyncTree(s,c,t,l,FALSE,Merge)
#define | CmpAllocateMasterPostBlock(b) CmpAllocatePostBlock(b,REG_NOTIFY_MASTER_POST,NULL,NULL)
#define | CmpAllocateSlavePostBlock(b, k, m) CmpAllocatePostBlock(b,0,k,m)
#define | SetUsed(Hive, Cell)
#define | CM_HARDWARE_PROFILE_STR_DATABASE L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\IDConfigDB"
#define | CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles"
#define | CM_HARDWARE_PROFILE_STR_CCS_CURRENT L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"
#define | CM_HARDWARE_PROFILE_STR_ALIAS L"Alias"
#define | CM_HARDWARE_PROFILE_STR_ACPI_ALIAS L"AcpiAlias"
#define | CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES L"Hardware Profiles"
#define | CM_HARDWARE_PROFILE_STR_DOCKING_STATE L"DockingState"
#define | CM_HARDWARE_PROFILE_STR_CAPABILITIES L"Capabilities"
#define | CM_HARDWARE_PROFILE_STR_DOCKID L"DockID"
#define | CM_HARDWARE_PROFILE_STR_SERIAL_NUMBER L"SerialNumber"
#define | CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER L"AcpiSerialNumber"
#define | CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER L"ProfileNumber"
#define | CM_HARDWARE_PROFILE_STR_ALIASABLE L"Aliasable"
#define | CM_HARDWARE_PROFILE_STR_CLONED L"Cloned"
#define | CM_HARDWARE_PROFILE_STR_PRISTINE L"Pristine"
#define | CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER L"PreferenceOrder"
#define | CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME L"FriendlyName"
#define | CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO L"CurrentDockInfo"
#define | CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID L"HwProfileGuid"
#define | CM_HARDWARE_PROFILE_STR_DOCKED L"Docked"
#define | CM_HARDWARE_PROFILE_STR_UNDOCKED L"Undocked"
#define | CM_HARDWARE_PROFILE_STR_UNKNOWN L"Unknown"
#define | CM_HP_FLAGS_ALIASABLE 1
#define | CM_HP_FLAGS_TRUE_MATCH 2
#define | CM_HP_FLAGS_PRISTINE 4
#define | CM_HP_FLAGS_DUPLICATE 8
#define | CmpSetIoStatus(Iosb, s, i, UseIosb32)

## Typedefs

typedef _BOOT_DRIVER_NODE | BOOT_DRIVER_NODE
typedef _BOOT_DRIVER_NODE * | PBOOT_DRIVER_NODE
typedef _CM_KEY_BODY | CM_KEY_BODY
typedef _CM_KEY_BODY * | PCM_KEY_BODY
typedef _CM_POST_KEY_BODY | CM_POST_KEY_BODY
typedef _CM_POST_KEY_BODY * | PCM_POST_KEY_BODY
typedef _CM_NOTIFY_BLOCK | CM_NOTIFY_BLOCK
typedef _CM_NOTIFY_BLOCK * | PCM_NOTIFY_BLOCK
typedef enum _POST_BLOCK_TYPE | POST_BLOCK_TYPE
typedef _CM_SYNC_POST_BLOCK | CM_SYNC_POST_BLOCK
typedef _CM_SYNC_POST_BLOCK * | PCM_SYNC_POST_BLOCK
typedef _CM_ASYNC_USER_POST_BLOCK | CM_ASYNC_USER_POST_BLOCK
typedef _CM_ASYNC_USER_POST_BLOCK * | PCM_ASYNC_USER_POST_BLOCK
typedef _CM_ASYNC_KERNEL_POST_BLOCK | CM_ASYNC_KERNEL_POST_BLOCK
typedef _CM_ASYNC_KERNEL_POST_BLOCK * | PCM_ASYNC_KERNEL_POST_BLOCK
typedef _CM_POST_BLOCK_UNION | CM_POST_BLOCK_UNION
typedef _CM_POST_BLOCK_UNION * | PCM_POST_BLOCK_UNION
typedef _CM_POST_BLOCK | CM_POST_BLOCK
typedef _CM_POST_BLOCK * | PCM_POST_BLOCK
typedef _CMHIVE | CMHIVE
typedef _CMHIVE * | PCMHIVE
typedef _REGISTRY_COMMAND | REGISTRY_COMMAND
typedef _REGISTRY_COMMAND * | PREGISTRY_COMMAND
typedef _CM_PARSE_CONTEXT | CM_PARSE_CONTEXT
typedef _CM_PARSE_CONTEXT * | PCM_PARSE_CONTEXT
typedef ULONG(* | PKCB_WORKER_ROUTINE )(PCM_KEY_CONTROL_BLOCK Current, PVOID Context1, PVOID Context2)
typedef _HIVE_LIST_ENTRY | HIVE_LIST_ENTRY
typedef _HIVE_LIST_ENTRY * | PHIVE_LIST_ENTRY
typedef _CM_HARDWARE_PROFILE | CM_HARDWARE_PROFILE
typedef _CM_HARDWARE_PROFILE * | PCM_HARDWARE_PROFILE
typedef _CM_HARDWARE_PROFILE_LIST | CM_HARDWARE_PROFILE_LIST
typedef _CM_HARDWARE_PROFILE_LIST * | PCM_HARDWARE_PROFILE_LIST
typedef _CM_HARDWARE_PROFILE_ALIAS | CM_HARDWARE_PROFILE_ALIAS
typedef _CM_HARDWARE_PROFILE_ALIAS * | PCM_HARDWARE_PROFILE_ALIAS
typedef _CM_HARDWARE_PROFILE_ALIAS_LIST | CM_HARDWARE_PROFILE_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ALIAS_LIST * | PCM_HARDWARE_PROFILE_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS | CM_HARDWARE_PROFILE_ACPI_ALIAS
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS * | PCM_HARDWARE_PROFILE_ACPI_ALIAS
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST | CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST * | PCM_HARDWARE_PROFILE_ACPI_ALIAS_LIST
typedef NTSTATUS(* | PCM_ACPI_SELECTION_ROUTINE )(IN PCM_HARDWARE_PROFILE_LIST ProfileList, OUT PULONG ProfileIndexToUse, IN PVOID Context)

## Enumerations

enum | _POST_BLOCK_TYPE { PostSynchronous = 1, PostAsyncUser = 2, PostAsyncKernel = 3 }

## Functions

ULONG | CmpCheckLockExceptionFilter (IN PEXCEPTION_POINTERS ExceptionPointers)
NTSTATUS | 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 | CmpDoCreate (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PACCESS_STATE AccessState, IN PUNICODE_STRING Name, IN KPROCESSOR_MODE AccessMode, IN PCM_PARSE_CONTEXT Context, IN PCM_KEY_CONTROL_BLOCK ParentKcb, OUT PVOID *Object)
NTSTATUS | CmpDoCreateChild (IN PHHIVE Hive, IN HCELL_INDEX ParentCell, IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PACCESS_STATE AccessState, IN PUNICODE_STRING Name, IN KPROCESSOR_MODE AccessMode, IN PCM_PARSE_CONTEXT Context, IN PCM_KEY_CONTROL_BLOCK ParentKcb, IN USHORT Flags, OUT PHCELL_INDEX KeyCell, OUT PVOID *Object)
NTSTATUS | CmpQueryKeyName (IN PVOID Object, IN BOOLEAN HasObjectName, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
VOID | CmpDeleteKeyObject (IN PVOID Object)
VOID | CmpCloseKeyObject (IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
NTSTATUS | CmpSecurityMethod (IN PVOID Object, IN SECURITY_OPERATION_CODE OperationCode, IN PSECURITY_INFORMATION SecurityInformation, IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG CapturedLength, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping)
VOID | CmpSearchKeyControlBlockTree (PKCB_WORKER_ROUTINE WorkerRoutine, PVOID Context1, PVOID Context2)
PVOID | CmpAllocate (ULONG Size, BOOLEAN UseForIo)
VOID | CmpFree (PVOID MemoryBlock, ULONG GlobalQuotaSize)
BOOLEAN | CmpFileSetSize (PHHIVE Hive, ULONG FileType, ULONG FileSize)
NTSTATUS | CmpDoFileSetSize (PHHIVE Hive, ULONG FileType, ULONG FileSize)
BOOLEAN | CmpFileWrite (PHHIVE Hive, ULONG FileType, PCMP_OFFSET_ARRAY offsetArray, ULONG offsetArrayCount, PULONG FileOffset)
BOOLEAN | CmpFileRead (PHHIVE Hive, ULONG FileType, PULONG FileOffset, PVOID DataBuffer, ULONG DataLength)
BOOLEAN | CmpFileFlush (PHHIVE Hive, ULONG FileType)
NTSTATUS | CmpCreateEvent (IN EVENT_TYPE eventType, OUT PHANDLE eventHandle, OUT PKEVENT *event)
NTSTATUS | CmDeleteKey (IN PCM_KEY_BODY KeyBody)
NTSTATUS | CmDeleteValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN UNICODE_STRING ValueName)
NTSTATUS | CmEnumerateKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmEnumerateValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmFlushKey (IN PHHIVE Hive, IN HCELL_INDEX Cell)
NTSTATUS | CmQueryKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmQueryValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN UNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS | CmQueryMultipleValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PKEY_VALUE_ENTRY ValueEntries, IN ULONG EntryCount, IN PVOID ValueBuffer, IN OUT PULONG BufferLength, IN OPTIONAL PULONG ResultLength)
NTSTATUS | CmRenameValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN UNICODE_STRING SourceValueName, IN UNICODE_STRING TargetValueName, IN ULONG TargetIndex)
NTSTATUS | CmReplaceKey (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PUNICODE_STRING NewHiveName, IN PUNICODE_STRING OldFileName)
NTSTATUS | CmRestoreKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN HANDLE FileHandle, IN ULONG Flags)
NTSTATUS | CmSaveKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN HANDLE FileHandle)
NTSTATUS | CmSaveMergedKeys (IN PCM_KEY_CONTROL_BLOCK HighPrecedenceKcb, IN PCM_KEY_CONTROL_BLOCK LowPrecedenceKcb, IN HANDLE FileHandle)
NTSTATUS | CmSetValueKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
NTSTATUS | CmSetLastWriteTimeKey (IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PLARGE_INTEGER LastWriteTime)
NTSTATUS | CmpNotifyChangeKey (IN PCM_KEY_BODY KeyBody, IN PCM_POST_BLOCK PostBlock, IN ULONG CompletionFilter, IN BOOLEAN WatchTree, IN PVOID Buffer, IN ULONG BufferSize, IN PCM_POST_BLOCK MasterPostBlock)
NTSTATUS | CmLoadKey (IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags)
NTSTATUS | CmUnloadKey (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PCM_KEY_CONTROL_BLOCK Kcb)
BOOLEAN | CmpMarkKeyDirty (PHHIVE Hive, HCELL_INDEX Cell)
BOOLEAN | CmpDoFlushAll (VOID)
VOID | CmpLazyFlush (VOID)
VOID | CmpQuotaWarningWorker (IN PVOID WorkItem)
VOID | CmpComputeGlobalQuotaAllowed (VOID)
BOOLEAN | CmpClaimGlobalQuota (IN ULONG Size)
VOID | CmpReleaseGlobalQuota (IN ULONG Size)
VOID | CmpSetGlobalQuotaAllowed (VOID)
NTSTATUS | CmpAssignSecurityDescriptor (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PCM_KEY_NODE Node, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
BOOLEAN | CmpCheckCreateAccess (IN PUNICODE_STRING RelativeName, IN PSECURITY_DESCRIPTOR Descriptor, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE PreviousMode, IN ACCESS_MASK AdditionalAccess, OUT PNTSTATUS AccessStatus)
BOOLEAN | CmpCheckNotifyAccess (IN PCM_NOTIFY_BLOCK NotifyBlock, IN PHHIVE Hive, IN PCM_KEY_NODE Node)
PSECURITY_DESCRIPTOR | CmpHiveRootSecurityDescriptor (VOID)
VOID | CmpFreeSecurityDescriptor (IN PHHIVE Hive, IN HCELL_INDEX Cell)
VOID | CmpLockRegistryExclusive (VOID)
VOID | CmpLockRegistry (VOID)
BOOLEAN | CmpIsLastKnownGoodBoot (VOID)
VOID | CmpUnlockRegistry ()
NTSTATUS | CmpQueryKeyData (PHHIVE Hive, PCM_KEY_NODE Node, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength)
VOID | CmpFreeKeyBody (PHHIVE Hive, HCELL_INDEX Cell)
VOID | CmpFreeValue (PHHIVE Hive, HCELL_INDEX Cell)
HCELL_INDEX | CmpFindValueByName (PHHIVE Hive, PCM_KEY_NODE KeyNode, PUNICODE_STRING Name)
NTSTATUS | CmpDeleteChildByName (PHHIVE Hive, HCELL_INDEX Cell, UNICODE_STRING Name, PHCELL_INDEX ChildCell)
NTSTATUS | CmpFreeKeyByCell (PHHIVE Hive, HCELL_INDEX Cell, BOOLEAN Unlink)
HCELL_INDEX | CmpFindNameInList (IN PHHIVE Hive, IN PCHILD_LIST ChildList, IN PUNICODE_STRING Name, IN OPTIONAL PCELL_DATA *ChildAddress, IN OPTIONAL PULONG ChildIndex)
HCELL_INDEX | CmpCopyCell (PHHIVE SourceHive, HCELL_INDEX SourceCell, PHHIVE TargetHive, HSTORAGE_TYPE Type)
HCELL_INDEX | CmpCopyValue (PHHIVE SourceHive, HCELL_INDEX SourceValueCell, PHHIVE TargetHive, HSTORAGE_TYPE Type)
HCELL_INDEX | CmpCopyKeyPartial (PHHIVE SourceHive, HCELL_INDEX SourceKeyCell, PHHIVE TargetHive, HCELL_INDEX Parent, BOOLEAN CopyValues)
BOOLEAN | CmpCopySyncTree (PHHIVE SourceHive, HCELL_INDEX SourceCell, PHHIVE TargetHive, HCELL_INDEX TargetCell, BOOLEAN CopyVolatile, CMP_COPY_TYPE CopyType)
VOID | CmpDeleteTree (PHHIVE Hive, HCELL_INDEX Cell)
VOID | CmpSetVersionData (VOID)
NTSTATUS | CmpInitializeHardwareConfiguration (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
NTSTATUS | CmpInitializeMachineDependentConfiguration (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
NTSTATUS | CmpInitializeRegistryNode (IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE ParentHandle, OUT PHANDLE NewHandle, IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PUSHORT DeviceIndexTable)
NTSTATUS | CmpInitializeHive (PCMHIVE *CmHive, ULONG OperationType, ULONG HiveFlags, ULONG FileType, PVOID HiveData OPTIONAL, HANDLE Primary, HANDLE Alternate, HANDLE Log, HANDLE External, PUNICODE_STRING FileName)
BOOLEAN | CmpDestroyHive (IN PHHIVE Hive, IN HCELL_INDEX Cell)
VOID | CmpInitializeRegistryNames (VOID)
VOID | CmpInitializeCache (VOID)
PCM_KEY_CONTROL_BLOCK | CmpCreateKeyControlBlock (PHHIVE Hive, HCELL_INDEX Cell, PCM_KEY_NODE Node, PCM_KEY_CONTROL_BLOCK ParentKcb, BOOLEAN FakeKey, PUNICODE_STRING KeyName)
ULONG | CmpSearchForOpenSubKeys (IN PCM_KEY_CONTROL_BLOCK SearchKey, IN SUBKEY_SEARCH_TYPE SearchType)
VOID | CmpDereferenceKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpRemoveKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpReportNotify (PCM_KEY_CONTROL_BLOCK KeyControlBlock, PHHIVE Hive, HCELL_INDEX Cell, ULONG NotifyMask)
VOID | CmpPostNotify (PCM_NOTIFY_BLOCK NotifyBlock, PUNICODE_STRING Name OPTIONAL, ULONG Filter, NTSTATUS Status, PLIST_ENTRY ExternalKeyDeref OPTIONAL)
PCM_POST_BLOCK | CmpAllocatePostBlock (IN POST_BLOCK_TYPE BlockType, IN ULONG PostFlags, IN PCM_KEY_BODY KeyBody, IN PCM_POST_BLOCK MasterBlock)
VOID | CmpFreePostBlock (IN PCM_POST_BLOCK PostBlock)
VOID | CmpPostApc (struct _KAPC *Apc, PKNORMAL_ROUTINE *NormalRoutine, PVOID *NormalContext, PVOID *SystemArgument1, PVOID *SystemArgument2)
VOID | CmpFlushNotify (PCM_KEY_BODY KeyBody)
VOID | CmpPostApcRunDown (struct _KAPC *Apc)
NTSTATUS | CmpOpenHiveFiles (PUNICODE_STRING BaseName, PWSTR Extension OPTIONAL, PHANDLE Primary, PHANDLE Secondary, PULONG PrimaryDisposition, PULONG SecondaryDispoition, BOOLEAN CreateAllowed, BOOLEAN MarkAsSystemHive, PULONG ClusterSize)
NTSTATUS | CmpLinkHiveToMaster (PUNICODE_STRING LinkName, HANDLE RootDirectory, PCMHIVE CmHive, BOOLEAN Allocate, PSECURITY_DESCRIPTOR SecurityDescriptor)
VOID | CmpWorker (IN OUT PREGISTRY_COMMAND Command)
NTSTATUS | CmpSaveBootControlSet (IN USHORT ControlSetNum)
ULONG | CmCheckRegistry (PCMHIVE CmHive, BOOLEAN Clean)
BOOLEAN | CmpValidateHiveSecurityDescriptors (IN PHHIVE Hive)
HCELL_INDEX | CmpFindControlSet (IN PHHIVE SystemHive, IN HCELL_INDEX RootCell, IN PUNICODE_STRING SelectName, OUT PBOOLEAN AutoSelect)
BOOLEAN | CmpFindDrivers (IN PHHIVE Hive, IN HCELL_INDEX ControlSet, IN SERVICE_LOAD_TYPE LoadType, IN PWSTR BootFileSystem OPTIONAL, IN PLIST_ENTRY DriverListHead)
BOOLEAN | CmpFindNLSData (IN PHHIVE Hive, IN HCELL_INDEX ControlSet, OUT PUNICODE_STRING AnsiFilename, OUT PUNICODE_STRING OemFilename, OUT PUNICODE_STRING CaseTableFilename, OUT PUNICODE_STRING OemHalFilename)
HCELL_INDEX | CmpFindProfileOption (IN PHHIVE Hive, IN HCELL_INDEX ControlSet, OUT PCM_HARDWARE_PROFILE_LIST *ProfileList, OUT PCM_HARDWARE_PROFILE_ALIAS_LIST *AliasList, OUT PULONG Timeout)
VOID | CmpSetCurrentProfile (IN PHHIVE Hive, IN HCELL_INDEX ControlSet, IN PCM_HARDWARE_PROFILE Profile)
BOOLEAN | CmpResolveDriverDependencies (IN PLIST_ENTRY DriverListHead)
BOOLEAN | CmpSortDriverList (IN PHHIVE Hive, IN HCELL_INDEX ControlSet, IN PLIST_ENTRY DriverListHead)
HCELL_INDEX | CmpFindSubKeyByName (PHHIVE Hive, PCM_KEY_NODE Parent, PUNICODE_STRING SearchName)
HCELL_INDEX | CmpFindSubKeyByNumber (PHHIVE Hive, PCM_KEY_NODE Parent, ULONG Number)
BOOLEAN | CmpAddSubKey (PHHIVE Hive, HCELL_INDEX Parent, HCELL_INDEX Child)
BOOLEAN | CmpMarkIndexDirty (PHHIVE Hive, HCELL_INDEX ParentKey, HCELL_INDEX TargetKey)
BOOLEAN | CmpRemoveSubKey (PHHIVE Hive, HCELL_INDEX ParentKey, HCELL_INDEX TargetKey)
BOOLEAN | CmpGetNextName (IN OUT PUNICODE_STRING RemainingName, OUT PUNICODE_STRING NextName, OUT PBOOLEAN Last)
NTSTATUS | CmpAddToHiveFileList (PCMHIVE CmHive)
VOID | CmpRemoveFromHiveFileList ()
NTSTATUS | CmpInitHiveFromFile (IN PUNICODE_STRING FileName, IN ULONG HiveFlags, OUT PCMHIVE *CmHive, IN OUT PBOOLEAN Allocate, IN OUT PBOOLEAN RegistryLocked)
NTSTATUS | CmpCloneHwProfile (IN HANDLE IDConfigDB, IN HANDLE Parent, IN HANDLE OldProfile, IN ULONG OldProfileNumber, IN USHORT DockingState, OUT PHANDLE NewProfile, OUT PULONG NewProfileNumber)
NTSTATUS | CmpCreateHwProfileFriendlyName (IN HANDLE IDConfigDB, IN ULONG DockingState, IN ULONG NewProfileNumber, OUT PUNICODE_STRING FriendlyName)
NTSTATUS | CmSetAcpiHwProfile (IN PPROFILE_ACPI_DOCKING_STATE DockState, IN PCM_ACPI_SELECTION_ROUTINE, IN PVOID Context, OUT PHANDLE NewProfile, OUT PBOOLEAN ProfileChanged)
NTSTATUS | CmpAddAcpiAliasEntry (IN HANDLE IDConfigDB, IN PPROFILE_ACPI_DOCKING_STATE NewDockState, IN ULONG ProfileNumber, IN PWCHAR nameBuffer, IN PVOID valueBuffer, IN ULONG valueBufferLength, IN BOOLEAN PreventDuplication)
USHORT | CmpNameSize (IN PHHIVE Hive, IN PUNICODE_STRING Name)
USHORT | CmpCopyName (IN PHHIVE Hive, IN PWCHAR Destination, IN PUNICODE_STRING Source)
VOID | CmpCopyCompressedName (IN PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
LONG | CmpCompareCompressedName (IN PUNICODE_STRING SearchName, IN PWCHAR CompressedName, IN ULONG NameLength)
USHORT | CmpCompressedNameSize (IN PWCHAR Name, IN ULONG Length)
PCM_NAME_CONTROL_BLOCK | CmpGetNameControlBlock (PUNICODE_STRING NodeName)
VOID | CmpDereferenceKeyControlBlockWithLock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpCleanUpSubKeyInfo (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpCleanUpKcbValueCache (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpCleanUpKcbCacheWithLock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpRemoveFromDelayedClose (IN PCM_KEY_CONTROL_BLOCK kcb)
PUNICODE_STRING | CmpConstructName (PCM_KEY_CONTROL_BLOCK kcb)
PCELL_DATA | CmpGetValueListFromCache (IN PHHIVE Hive, IN PCACHED_CHILD_LIST ChildList, IN OUT BOOLEAN *IndexCached)
PCM_KEY_VALUE | CmpGetValueKeyFromCache (IN PHHIVE Hive, IN PCELL_DATA List, IN ULONG Index, OUT PPCM_CACHED_VALUE *ContainingList, IN BOOLEAN IndexCached, OUT BOOLEAN *ValueCached)
PCM_KEY_VALUE | CmpFindValueByNameFromCache (IN PHHIVE Hive, IN PCACHED_CHILD_LIST ChildList, IN PUNICODE_STRING Name, OUT PPCM_CACHED_VALUE *ContainingList, OUT ULONG *Index, OUT BOOLEAN *ValueCached)
NTSTATUS | CmpQueryKeyValueData (PHHIVE Hive, PCM_CACHED_VALUE *ContainingList, PCM_KEY_VALUE ValueKey, BOOLEAN ValueCached, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength)
BOOLEAN | CmpReferenceKeyControlBlock (PCM_KEY_CONTROL_BLOCK KeyControlBlock)
VOID | CmpInitializeKeyNameString (PCM_KEY_NODE Cell, PUNICODE_STRING KeyName, WCHAR *NameBuffer)
VOID | CmpInitializeValueNameString (PCM_KEY_VALUE Cell, PUNICODE_STRING ValueName, WCHAR *NameBuffer)

## Variables

ULONG | WmiUsePerfClock
PCM_TRACE_NOTIFY_ROUTINE | CmpTraceRoutine
ULONG | CmpCacheOnFlag
FAST_MUTEX | CmpKcbLock
UNICODE_STRING | CmRegistrySystemCloneName
POBJECT_TYPE | CmpKeyObjectType
FAST_MUTEX | CmpPostLock
BOOLEAN | CmpLazyFlushPending
ERESOURCE | CmpRegistryLock
ULONG | CmpHashTableSize
PCM_KEY_HASH * | CmpCacheTable

## Define Documentation

#define _CM_ENTRYLIST_MANIPULATION

| Definition at line 45 of file cmp.h.

#define _WMI_TRACING_REGISTRYCALLS

| Definition at line 62 of file cmp.h.

#define ASSERT_CM_LOCK_OWNED | (

)

| Definition at line 345 of file cmp.h. Referenced by CmpCancelSlavePost(), CmpCheckNotifyAccess(), CmpFlushNotify(), CmpPostNotify(), CmpSetValueKeyExisting(), CmpUnlockRegistry(), and HvpGetCellPaged().

#define ASSERT_CM_LOCK_OWNED_EXCLUSIVE | (

)

| Definition at line 346 of file cmp.h. Referenced by CmDeleteKey(), CmDeleteValueKey(), CmpCleanUpSubKeyInfo(), CmpCreateLinkNode(), CmpDoCreate(), CmpDoCreateChild(), CmpNotifyChangeKey(), CmpSearchForOpenSubKeys(), CmpSecurityMethod(), CmpSetSecurityDescriptorInfo(), CmRestoreKey(), CmSetValueKey(), HvFreeCell(), and NtUnloadKey().

#define ASSERT_KEY_OBJECT | ( | x |  | ) | ASSERT(((PCM_KEY_BODY)x)->Type == KEY_BODY_TYPE)

| Definition at line 530 of file cmp.h. Referenced by CmpSecurityMethod().

#define ASSERT_KEYBODY_LIST_EMPTY | ( | kcb |  | ) |

| Definition at line 525 of file cmp.h. Referenced by CmpCleanUpKcbCacheWithLock(), and CmpCreateKeyControlBlock().

#define ASSERT_NODE | ( | x |  | ) | ASSERT(((PCM_KEY_NODE)x)->Signature == CM_KEY_NODE_SIGNATURE)

| Definition at line 531 of file cmp.h. Referenced by CmpAssignSecurityDescriptor(), CmpFreeSecurityDescriptor(), CmpGetKeySecurity(), and CmpInsertSecurityCellList().

#define ASSERT_PASSIVE_LEVEL | (

)

| Definition at line 360 of file cmp.h. Referenced by CmpDoFileSetSize(), CmpFileFlush(), CmpFileRead(), CmpFileWrite(), CmpInitializeHive(), CmpOpenFileWithExtremePrejudice(), CmpOpenHiveFiles(), and CmpWorker().

#define ASSERT_SECURITY | ( | x |  | ) | ASSERT(((PCM_KEY_SECURITY)x)->Signature == CM_KEY_SECURITY_SIGNATURE)

| Definition at line 532 of file cmp.h. Referenced by CmpFreeSecurityDescriptor(), CmpGetKeySecurity(), CmpInsertSecurityCellList(), and CmpSetSecurityDescriptorInfo().

#define BEGIN_LOCK_CHECKPOINT

Value:

    {                                                                       \
            ULONG   LockCountBefore,LockCountAfter;                             \
            LockCountBefore = ExIsResourceAcquiredShared(&CmpRegistryLock);     \
            LockCountBefore += ExIsResourceAcquiredExclusive(&CmpRegistryLock); \
            try {

Definition at line 319 of file cmp.h.

Referenced by NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtLoadKey2(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtRestoreKey(), NtSaveKey(), NtSaveMergedKeys(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define ClearMasterPostBlockFlag | ( | _post_ |  | ) | ( ((_post_)->NotifyType) &= ~REG_NOTIFY_MASTER_POST )

| Definition at line 634 of file cmp.h. Referenced by CmpPostNotify().

#define CLONE_CONTROL_SET FALSE

| Definition at line 417 of file cmp.h. Referenced by CmpSaveBootControlSet().

#define CM_BUGCHECK | ( | Code,
|  | Parm1,
|  | Parm2,
|  | Parm3,
|  | Parm4 |  | ) | KeBugCheckEx( Code, Parm1, Parm2, Parm3, Parm4 )

| Definition at line 373 of file cmp.h.

#define CM_CACHE_FAKE_KEY 0x00000001

| Definition at line 222 of file cmp.h. Referenced by CmpAddInfoAfterParseFailure().

#define CM_HARDWARE_PROFILE_STR_ACPI_ALIAS L"AcpiAlias"

| Definition at line 1573 of file cmp.h. Referenced by CmpAddAcpiAliasEntry(), and CmpGetAcpiProfileInformation().

#define CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER L"AcpiSerialNumber"

| Definition at line 1583 of file cmp.h. Referenced by CmpAddAcpiAliasEntry(), CmpGetAcpiProfileInformation(), and CmSetAcpiHwProfile().

#define CM_HARDWARE_PROFILE_STR_ALIAS L"Alias"

| Definition at line 1572 of file cmp.h. Referenced by CmpAddAliasEntry(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_ALIASABLE L"Aliasable"

| Definition at line 1585 of file cmp.h. Referenced by CmpCloneHwProfile(), CmpFindProfileOption(), and CmpGetAcpiProfileInformation().

#define CM_HARDWARE_PROFILE_STR_CAPABILITIES L"Capabilities"

| Definition at line 1580 of file cmp.h. Referenced by CmpAddDockingInfo(), and CmpCreateControlSet().

#define CM_HARDWARE_PROFILE_STR_CCS_CURRENT L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"

| Definition at line 1568 of file cmp.h. Referenced by CmSetAcpiHwProfile().

#define CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles"

| Definition at line 1567 of file cmp.h. Referenced by CmpMoveBiosAliasTable(), and CmSetAcpiHwProfile().

#define CM_HARDWARE_PROFILE_STR_CLONED L"Cloned"

| Definition at line 1586 of file cmp.h. Referenced by CmpCloneHwProfile(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO L"CurrentDockInfo"

| Definition at line 1593 of file cmp.h. Referenced by CmpCreateControlSet(), CmSetAcpiHwProfile(), and IopUpdateHardwareProfile().

#define CM_HARDWARE_PROFILE_STR_DATABASE L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\IDConfigDB"

| Definition at line 1566 of file cmp.h. Referenced by CmSetAcpiHwProfile(), and IopUpdateHardwareProfile().

#define CM_HARDWARE_PROFILE_STR_DOCKED L"Docked"

| Definition at line 1598 of file cmp.h. Referenced by CmpCreateHwProfileFriendlyName().

#define CM_HARDWARE_PROFILE_STR_DOCKID L"DockID"

| Definition at line 1581 of file cmp.h. Referenced by CmpAddDockingInfo(), CmpCreateControlSet(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_DOCKING_STATE L"DockingState"

| Definition at line 1579 of file cmp.h. Referenced by CmpAddAcpiAliasEntry(), CmpAddDockingInfo(), CmpCreateControlSet(), CmpGetAcpiProfileInformation(), and CmSetAcpiHwProfile().

#define CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME L"FriendlyName"

| Definition at line 1592 of file cmp.h. Referenced by CmpCloneHwProfile(), CmpFindProfileOption(), and CmpGetAcpiProfileInformation().

#define CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES L"Hardware Profiles"

| Definition at line 1574 of file cmp.h. Referenced by CmpCloneHwProfile(), CmpCreateHwProfileFriendlyName(), CmpGetAcpiProfileInformation(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID L"HwProfileGuid"

| Definition at line 1594 of file cmp.h. Referenced by CmpCloneHwProfile().

#define CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER L"PreferenceOrder"

| Definition at line 1591 of file cmp.h. Referenced by CmpCloneHwProfile(), CmpFindProfileOption(), and CmpGetAcpiProfileInformation().

#define CM_HARDWARE_PROFILE_STR_PRISTINE L"Pristine"

| Definition at line 1590 of file cmp.h. Referenced by CmpFindProfileOption(), and CmpGetAcpiProfileInformation().

#define CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER L"ProfileNumber"

| Definition at line 1584 of file cmp.h. Referenced by CmpAddAcpiAliasEntry(), CmpAddAliasEntry(), CmpGetAcpiProfileInformation(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_SERIAL_NUMBER L"SerialNumber"

| Definition at line 1582 of file cmp.h. Referenced by CmpAddDockingInfo(), CmpCreateControlSet(), and CmpMoveBiosAliasTable().

#define CM_HARDWARE_PROFILE_STR_UNDOCKED L"Undocked"

| Definition at line 1599 of file cmp.h. Referenced by CmpCreateHwProfileFriendlyName().

#define CM_HARDWARE_PROFILE_STR_UNKNOWN L"Unknown"

| Definition at line 1600 of file cmp.h. Referenced by CmpCreateHwProfileFriendlyName().

#define CM_HP_FLAGS_ALIASABLE 1

| Definition at line 1625 of file cmp.h. Referenced by CmpFilterAcpiDockingState(), CmpFindProfileOption(), and CmpGetAcpiProfileInformation().

#define CM_HP_FLAGS_DUPLICATE 8

| Definition at line 1628 of file cmp.h. Referenced by CmpFilterAcpiDockingState(), and CmSetAcpiHwProfile().

#define CM_HP_FLAGS_PRISTINE 4

| Definition at line 1627 of file cmp.h. Referenced by CmpFilterAcpiDockingState(), CmpFindProfileOption(), CmpGetAcpiProfileInformation(), and CmSetAcpiHwProfile().

#define CM_HP_FLAGS_TRUE_MATCH 2

| Definition at line 1626 of file cmp.h. Referenced by CmpFilterAcpiDockingState(), and CmSetAcpiHwProfile().

#define CM_MAX_REASONABLE_VALUES 100

| Definition at line 431 of file cmp.h. Referenced by CmpSetValueKeyNew().

#define CM_MAX_STASH 1024*1024

| Definition at line 428 of file cmp.h. Referenced by CmpSetValueKeyExisting(), and main().

#define CM_WRAP_LIMIT 0x7fffffff

| Definition at line 422 of file cmp.h. Referenced by CmpComputeGlobalQuotaAllowed(), CmReplaceKey(), CmSaveKey(), CmSaveMergedKeys(), and CmSetRegistryQuotaInformation().

#define CML_API 2

| Definition at line 243 of file cmp.h. Referenced by CmNotifyRunDown(), CmpFreePostBlock(), CmpNameFromAttributes(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmSetValueKey(), NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtLoadKey2(), NtNotifyChangeKey(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtRestoreKey(), NtSaveKey(), NtSaveMergedKeys(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define CML_API_ARGS 3

| Definition at line 244 of file cmp.h. Referenced by NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtLoadKey2(), NtOpenKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define CML_BIN 8

| Definition at line 249 of file cmp.h. Referenced by HvFreeHive(), HvInitializeHive(), and HvpEnlistBinInMap().

#define CML_BUGCHECK 1

| Definition at line 242 of file cmp.h. Referenced by CmGetSystemDriverList(), CmInitSystem1(), CmpAddAcpiAliasEntry(), CmpAddAliasEntry(), CmpCloneControlSet(), CmpCloneHwProfile(), CmpCreateControlSet(), CmpInitializeHiveList(), CmpInitializeSystemHive(), CmpLinkKeyToHive(), CmpOpenHiveFiles(), CmpValidateAlternate(), CmReplaceKey(), HvSyncHive(), and HvWriteHive().

#define CML_FLOW 7

| Definition at line 248 of file cmp.h. Referenced by CmpAssignSecurityDescriptor(), CmpCheckCreateAccess(), CmpCheckNotifyAccess(), CmpCreateLinkNode(), CmpDoCreate(), CmpDoCreateChild(), CmpDoOpen(), CmpFindMatchingDescriptorCell(), CmpFreeSecurityDescriptor(), CmpGetKeySecurity(), CmpGetObjectSecurity(), CmpGetSymbolicLink(), CmpInsertSecurityCellList(), CmpLazyFlush(), CmpLazyFlushDpcRoutine(), CmpLazyFlushWorker(), CmpLockRegistry(), CmpParseKey(), CmpQuerySecurityDescriptorInfo(), CmpRemoveSecurityCellList(), CmpSecurityMethod(), CmpSetSecurityDescriptorInfo(), CmpValidateHiveSecurityDescriptors(), CmSaveKey(), CmSaveMergedKeys(), HvpAddBin(), HvpBuildMap(), HvpBuildMapAndCopy(), HvpEnlistBinInMap(), HvpFindNextDirtyBlock(), HvpGetCellPaged(), HvpInitMap(), and HvSyncHive().

#define CML_MAJOR 5

| Definition at line 246 of file cmp.h. Referenced by CmFlushKey(), CmInitSystem1(), CmpAddSubKey(), CmpAddToHiveFileList(), CmpAddToLeaf(), CmpCancelSlavePost(), CmpCloseKeyObject(), CmpCopySyncTree(), CmpCreateLinkNode(), CmpCreateObjectTypes(), CmpCreateRegistryRoot(), CmpCreateRootNode(), CmpDeleteKeyObject(), CmpDeleteTree(), CmpFileFlush(), CmpFileRead(), CmpFileSetSize(), CmpFileWrite(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), CmpFlushNotify(), CmpFreePostBlock(), CmpFreeSlavePost(), CmpHiveRootSecurityDescriptor(), CmpInitializeHive(), CmpInitializeHiveList(), CmpIsLastKnownGoodBoot(), CmpLinkHiveToMaster(), CmpParseKey(), CmpPostApc(), CmpPostApcRunDown(), CmpPostNotify(), CmpSelectLeaf(), CmpSplitLeaf(), CmpValidateHiveSecurityDescriptors(), CmRestoreKey(), CmSaveKey(), CmSaveMergedKeys(), HvInitializeHive(), and HvWriteHive().

#define CML_MINOR 6

| Definition at line 247 of file cmp.h. Referenced by CmpAllocate(), CmpCopyCell(), CmpCopyKeyPartial(), CmpCopySyncTree2(), CmpCopyValue(), CmpDestroyTemporaryHive(), CmpDoOpen(), CmpFree(), CmpGetSymbolicLink(), CmpInitializeHiveList(), CmpNotifyChangeKey(), CmpParseKey(), CmpQueryKeyName(), CmpValidateHiveSecurityDescriptors(), HvFreeCell(), HvIsBinDirty(), HvMarkCellDirty(), HvMarkClean(), HvMarkDirty(), HvpDoWriteHive(), HvpGrowLog1(), HvpGrowLog2(), and HvpWriteLog().

#define CML_WORKER 4

| Definition at line 245 of file cmp.h. Referenced by CmDeleteKey(), CmDeleteValueKey(), CmEnumerateKey(), CmEnumerateValueKey(), CmFlushKey(), CmpNotifyChangeKey(), CmpReportNotify(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), CmSetLastWriteTimeKey(), CmSetValueKey(), CmUnloadKey(), and HvSyncHive().

#define CmLockHive | ( | _hive_ |  | ) |

Value:

    ASSERT( (_hive_)->HiveLock );\
                                ExAcquireFastMutexUnsafe((_hive_)->HiveLock)

Definition at line 660 of file cmp.h.

Referenced by CmFlushKey(), CmpCloseKeyObject(), CmpDoFlushAll(), and CmpFlushNotify().

#define CMLOG | ( | level,
|  | select |  | ) | if (0) {}

| Definition at line 293 of file cmp.h. Referenced by CmDeleteKey(), CmDeleteValueKey(), CmEnumerateKey(), CmEnumerateValueKey(), CmFlushKey(), CmGetSystemDriverList(), CmInitSystem1(), CmNotifyRunDown(), CmpAddAcpiAliasEntry(), CmpAddAliasEntry(), CmpAddSubKey(), CmpAddToHiveFileList(), CmpAddToLeaf(), CmpAllocate(), CmpAssignSecurityDescriptor(), CmpCancelSlavePost(), CmpCheckCreateAccess(), CmpCheckNotifyAccess(), CmpCloneControlSet(), CmpCloneHwProfile(), CmpCloseKeyObject(), CmpCopyCell(), CmpCopyKeyPartial(), CmpCopySyncTree(), CmpCopySyncTree2(), CmpCopyValue(), CmpCreateControlSet(), CmpCreateLinkNode(), CmpCreateObjectTypes(), CmpCreateRegistryRoot(), CmpCreateRootNode(), CmpDeleteKeyObject(), CmpDeleteTree(), CmpDestroyTemporaryHive(), CmpDoCreate(), CmpDoCreateChild(), CmpDoOpen(), CmpFileFlush(), CmpFileRead(), CmpFileSetSize(), CmpFileWrite(), CmpFindMatchingDescriptorCell(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), CmpFlushNotify(), CmpFree(), CmpFreePostBlock(), CmpFreeSecurityDescriptor(), CmpFreeSlavePost(), CmpGetKeySecurity(), CmpGetObjectSecurity(), CmpGetSymbolicLink(), CmpHiveRootSecurityDescriptor(), CmpInitializeHive(), CmpInitializeHiveList(), CmpInitializeSystemHive(), CmpInsertSecurityCellList(), CmpIsLastKnownGoodBoot(), CmpLazyFlush(), CmpLazyFlushDpcRoutine(), CmpLazyFlushWorker(), CmpLinkHiveToMaster(), CmpLinkKeyToHive(), CmpLockRegistry(), CmpNameFromAttributes(), CmpNotifyChangeKey(), CmpOpenHiveFiles(), CmpParseKey(), CmpPostApc(), CmpPostApcRunDown(), CmpPostNotify(), CmpQueryKeyName(), CmpQuerySecurityDescriptorInfo(), CmpRemoveSecurityCellList(), CmpReportNotify(), CmpSecurityMethod(), CmpSelectLeaf(), CmpSetSecurityDescriptorInfo(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), CmpValidateAlternate(), CmpValidateHiveSecurityDescriptors(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), CmReplaceKey(), CmRestoreKey(), CmSaveKey(), CmSaveMergedKeys(), CmSetLastWriteTimeKey(), CmSetValueKey(), CmUnloadKey(), HvFreeCell(), HvFreeHive(), HvInitializeHive(), HvIsBinDirty(), HvMarkCellDirty(), HvMarkClean(), HvMarkDirty(), HvpAddBin(), HvpBuildMap(), HvpBuildMapAndCopy(), HvpDoWriteHive(), HvpEnlistBinInMap(), HvpFindNextDirtyBlock(), HvpGetCellPaged(), HvpGrowLog1(), HvpGrowLog2(), HvpInitMap(), HvpWriteLog(), HvSyncHive(), HvWriteHive(), NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtLoadKey2(), NtNotifyChangeKey(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtRestoreKey(), NtSaveKey(), NtSaveMergedKeys(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define CmpAllocateMasterPostBlock | ( | b |  | ) | CmpAllocatePostBlock(b,REG_NOTIFY_MASTER_POST,NULL,NULL)

| Definition at line 1471 of file cmp.h. Referenced by NtNotifyChangeMultipleKeys().

#define CmpAllocateSlavePostBlock | ( | b,
|  | k,
|  | m |  | ) | CmpAllocatePostBlock(b,0,k,m)

| Definition at line 1481 of file cmp.h. Referenced by NtNotifyChangeMultipleKeys().

#define CmpAllocateTag | ( | a,
|  | b,
|  | c |  | ) | CmpAllocate(a,b)

| Definition at line 214 of file cmp.h.

#define CmpClearListEntry | ( | a |  | ) | (a)->Flink = (a)->Blink = NULL

| Definition at line 54 of file cmp.h. Referenced by CmNotifyRunDown(), CmpFlushNotify(), CmpFreePostBlock(), and CmpPostNotify().

#define CmpCopyTree | ( | s,
|  | c,
|  | t,
|  | l |  | ) | CmpCopySyncTree(s,c,t,l,FALSE,Copy)

| Definition at line 1314 of file cmp.h. Referenced by CmpCloneControlSet(), CmpCloneHwProfile(), CmpLoadHiveVolatile(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

#define CmpCopyTreeEx | ( | s,
|  | c,
|  | t,
|  | l,
|  | f |  | ) | CmpCopySyncTree(s,c,t,l,f,Copy)

| Definition at line 1327 of file cmp.h. Referenced by CmpSaveBootControlSet().

#define CmpDumpSecurityDescriptor | ( | x,
|  | y |  | ) |

| Definition at line 400 of file cmp.h. Referenced by CmpAssignSecurityDescriptor(), CmpCheckCreateAccess(), CmpCheckNotifyAccess(), CmpSetSecurityDescriptorInfo(), and CmpValidateHiveSecurityDescriptors().

#define CmpFindValueByName | ( | h,
|  | k,
|  | n |  | ) | CmpFindNameInList(h,&((k)->ValueList),n,NULL,NULL)

| Definition at line 1243 of file cmp.h. Referenced by CmGetSystemControlValues(), CmpAddDriverToList(), CmpFindControlSet(), CmpFindNLSData(), CmpFindProfileOption(), CmpFindTagIndex(), CmpGetSymbolicLink(), CmpIsLoadType(), CmpSetCurrentProfile(), CmpSortDriverList(), and CmQueryMultipleValueKey().

#define CmpHKeyNameLen | ( | Key |  | ) |

Value:

    (((Key)->Flags & KEY_COMP_NAME) ? \
                CmpCompressedNameSize((Key)->Name,(Key)->NameLength) : \
                (Key)->NameLength)

Definition at line 673 of file cmp.h.

Referenced by CmpGetHiveName(), CmpLoadHiveVolatile(), and CmpQueryKeyData().

#define CmpHKeyNodeSize | ( | Hive,
|  | KeyName |  | ) | (FIELD_OFFSET(CM_KEY_NODE, Name) + CmpNameSize(Hive, KeyName))

| Definition at line 683 of file cmp.h. Referenced by CmpCreateLinkNode(), CmpCreateRootNode(), CmpDoCreateChild(), and EhCreateChild().

#define CmpHKeyValueSize | ( | Hive,
|  | ValueName |  | ) | (FIELD_OFFSET(CM_KEY_VALUE, Name) + CmpNameSize(Hive, ValueName))

| Definition at line 697 of file cmp.h. Referenced by CmpSetValueKeyNew().

#define CmpMakeSpecialPoolReadOnly | ( | a |  | ) |

| Definition at line 142 of file cmp.h. Referenced by CmpGetValueDataFromCache(), CmpGetValueKeyFromCache(), and CmpGetValueListFromCache().

#define CmpMakeSpecialPoolReadWrite | ( | a |  | ) |

| Definition at line 143 of file cmp.h. Referenced by CmpCleanUpKcbValueCache(), CmpGetValueDataFromCache(), and CmpGetValueKeyFromCache().

#define CmpMakeValueCacheReadOnly | ( | a,
|  | b |  | ) |

| Definition at line 144 of file cmp.h. Referenced by CmEnumerateValueKey(), and CmQueryValueKey().

#define CmpMakeValueCacheReadWrite | ( | a,
|  | b |  | ) |

| Definition at line 145 of file cmp.h. Referenced by CmEnumerateValueKey(), and CmQueryValueKey().

#define CmpMarkAllBinsReadOnly | ( | a |  | ) |

| Definition at line 172 of file cmp.h. Referenced by CmDeleteKey(), CmDeleteValueKey(), CmEnumerateKey(), CmEnumerateValueKey(), CmFlushKey(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), and CmSetValueKey().

#define CmpMergeTrees | ( | s,
|  | c,
|  | t,
|  | l |  | ) | CmpCopySyncTree(s,c,t,l,FALSE,Merge)

| Definition at line 1351 of file cmp.h. Referenced by CmSaveMergedKeys().

#define CmpNcbNameLen | ( | Ncb |  | ) |

Value:

    (((Ncb)->Compressed) ? \
                CmpCompressedNameSize((Ncb)->Name,(Ncb)->NameLength) : \
                (Ncb)->NameLength)

Definition at line 678 of file cmp.h.

#define CmpRemoveEntryList | ( | a |  | ) |

Value:

    if(((a)->Flink != NULL) && ((a)->Blink != NULL) ) {     \
                RemoveEntryList(a);                                                 \
                (a)->Flink = (a)->Blink = NULL;                                 \
        }

Definition at line 48 of file cmp.h.

Referenced by CmNotifyRunDown(), CmpCancelSlavePost(), CmpFreeSlavePost(), CmpPostApc(), CmpPostApcRunDown(), CmpPostNotify(), and NtNotifyChangeMultipleKeys().

#define CmpSetIoStatus | ( | Iosb,
|  | s,
|  | i,
|  | UseIosb32 |  | ) |

Value:

    (Iosb)->Status = (s);                                                      \
    (Iosb)->Information = (i);                                                 \

Definition at line 2019 of file cmp.h.

Referenced by CmNotifyRunDown(), CmpPostApc(), CmpPostApcRunDown(), and NtNotifyChangeMultipleKeys().

#define CmpSyncTrees | ( | s,
|  | c,
|  | t,
|  | l,
|  | f |  | ) | CmpCopySyncTree(s,c,t,l,f,Sync)

| Definition at line 1339 of file cmp.h. Referenced by CmpSaveBootControlSet().

#define CmpValueNameLen | ( | Value |  | ) |

Value:

    (((Value)->Flags & VALUE_COMP_NAME) ?                           \
                CmpCompressedNameSize((Value)->Name,(Value)->NameLength) :  \
                (Value)->NameLength)

Definition at line 692 of file cmp.h.

Referenced by CmpQueryKeyValueData().

#define CmpWmiFireEvent | ( | Status,
|  | KeyHandle,
|  | ElapsedTime,
|  | KeyName,
|  | Type |  | ) |

Value:

    {                                                                   \
        PCM_TRACE_NOTIFY_ROUTINE TraceRoutine = CmpTraceRoutine;        \
        if( TraceRoutine != NULL ) {                                    \
            (*TraceRoutine)(Status,KeyHandle,ElapsedTime,KeyName,Type); \
        }                                                               \
    }

Definition at line 76 of file cmp.h.

#define CMS_BIN_MAP 0x00004000

| Definition at line 269 of file cmp.h. Referenced by HvFreeHive(), HvInitializeHive(), and HvpEnlistBinInMap().

#define CMS_CM 0x00000080

| Definition at line 262 of file cmp.h. Referenced by CmDeleteKey(), CmDeleteValueKey(), CmEnumerateKey(), CmEnumerateValueKey(), CmFlushKey(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), CmSetLastWriteTimeKey(), CmSetValueKey(), and CmUnloadKey().

#define CMS_CM_ERROR 0x00800000

| Definition at line 278 of file cmp.h.

#define CMS_DEFAULT ((~(CMS_MAP)) & 0xffffffff)

| Definition at line 286 of file cmp.h.

#define CMS_EXCEPTION 0x00001000

| Definition at line 267 of file cmp.h. Referenced by CmNotifyRunDown(), CmpNameFromAttributes(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmSetValueKey(), NtCreateKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtLoadKey2(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define CMS_HIVE 0x00000008

| Definition at line 258 of file cmp.h. Referenced by HvFreeCell(), HvpAddBin(), HvpBuildMap(), HvpBuildMapAndCopy(), HvpEnlistBinInMap(), and HvpInitMap().

#define CMS_HIVE_ERROR 0x00080000

| Definition at line 274 of file cmp.h.

#define CMS_INDEX 0x00002000

| Definition at line 268 of file cmp.h. Referenced by CmpAddSubKey(), CmpAddToLeaf(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), CmpSelectLeaf(), and CmpSplitLeaf().

#define CMS_INDEX_ERROR 0x10000000

| Definition at line 283 of file cmp.h.

#define CMS_INIT 0x00000002

| Definition at line 256 of file cmp.h. Referenced by CmInitSystem1(), CmpAddAcpiAliasEntry(), CmpAddAliasEntry(), CmpCloneControlSet(), CmpCloneHwProfile(), CmpCreateControlSet(), CmpInitializeHive(), CmpInitializeHiveList(), CmpIsLastKnownGoodBoot(), CmpLinkKeyToHive(), CmpValidateAlternate(), and HvInitializeHive().

#define CMS_INIT_ERROR 0x00020000

| Definition at line 272 of file cmp.h. Referenced by CmGetSystemDriverList(), CmInitSystem1(), CmpAddToHiveFileList(), CmpCreateObjectTypes(), CmpCreateRegistryRoot(), CmpCreateRootNode(), CmpInitializeHive(), CmpInitializeHiveList(), CmpInitializeSystemHive(), CmpLinkHiveToMaster(), and CmpOpenHiveFiles().

#define CMS_IO 0x00000010

| Definition at line 259 of file cmp.h. Referenced by CmpFileFlush(), CmpFileRead(), CmpFileWrite(), CmpLazyFlush(), CmpLazyFlushDpcRoutine(), CmpLazyFlushWorker(), HvIsBinDirty(), HvMarkCellDirty(), HvMarkClean(), HvMarkDirty(), HvpDoWriteHive(), HvpFindNextDirtyBlock(), HvpGrowLog1(), HvpGrowLog2(), HvpWriteLog(), HvSyncHive(), and HvWriteHive().

#define CMS_IO_ERROR 0x00100000

| Definition at line 275 of file cmp.h. Referenced by CmFlushKey(), CmpFileRead(), CmpFileSetSize(), and CmpFileWrite().

#define CMS_LOCKING 0x00000400

| Definition at line 265 of file cmp.h. Referenced by CmpLockRegistry().

#define CMS_LOCKING_ERROR 0x04000000

| Definition at line 281 of file cmp.h.

#define CMS_MAP 0x00000001

| Definition at line 255 of file cmp.h. Referenced by HvpGetCellPaged().

#define CMS_MAP_ERROR 0x00010000

| Definition at line 271 of file cmp.h.

#define CMS_NOTIFY 0x00000800

| Definition at line 266 of file cmp.h. Referenced by CmpCancelSlavePost(), CmpFlushNotify(), CmpFreePostBlock(), CmpFreeSlavePost(), CmpNotifyChangeKey(), CmpPostApc(), CmpPostApcRunDown(), CmpPostNotify(), and CmpReportNotify().

#define CMS_NOTIFY_ERROR 0x08000000

| Definition at line 282 of file cmp.h.

#define CMS_NTAPI 0x00000004

| Definition at line 257 of file cmp.h. Referenced by CmNotifyRunDown(), CmpCloseKeyObject(), CmpDeleteKeyObject(), CmpFreePostBlock(), NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtLoadKey2(), NtNotifyChangeKey(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtRestoreKey(), NtSaveKey(), NtSaveMergedKeys(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define CMS_NTAPI_ERROR 0x00040000

| Definition at line 273 of file cmp.h.

#define CMS_PARSE 0x00000020

| Definition at line 260 of file cmp.h. Referenced by CmpCreateLinkNode(), CmpDoCreate(), CmpDoCreateChild(), CmpDoOpen(), CmpGetSymbolicLink(), CmpParseKey(), and CmpQueryKeyName().

#define CMS_PARSE_ERROR 0x00200000

| Definition at line 276 of file cmp.h.

#define CMS_POOL 0x00000200

| Definition at line 264 of file cmp.h. Referenced by CmpAllocate(), CmpCloseKeyObject(), CmpDoOpen(), CmpFree(), and CmpNotifyChangeKey().

#define CMS_POOL_ERROR 0x02000000

| Definition at line 280 of file cmp.h.

#define CMS_SAVRES 0x00000040

| Definition at line 261 of file cmp.h. Referenced by CmpCopyCell(), CmpCopyKeyPartial(), CmpCopySyncTree(), CmpCopySyncTree2(), CmpCopyValue(), CmpDeleteTree(), CmpDestroyTemporaryHive(), CmReplaceKey(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

#define CMS_SAVRES_ERROR 0x00400000

| Definition at line 277 of file cmp.h.

#define CMS_SEC 0x00000100

| Definition at line 263 of file cmp.h. Referenced by CmpAssignSecurityDescriptor(), CmpCheckCreateAccess(), CmpCheckNotifyAccess(), CmpFindMatchingDescriptorCell(), CmpFreeSecurityDescriptor(), CmpGetKeySecurity(), CmpGetObjectSecurity(), CmpHiveRootSecurityDescriptor(), CmpInsertSecurityCellList(), CmpQuerySecurityDescriptorInfo(), CmpRemoveSecurityCellList(), CmpSecurityMethod(), CmpSetSecurityDescriptorInfo(), and CmpValidateHiveSecurityDescriptors().

#define CMS_SEC_ERROR 0x01000000

| Definition at line 279 of file cmp.h.

#define CmUnlockHive | ( | _hive_ |  | ) |

Value:

    ASSERT( (_hive_)->HiveLock );\
                                 ExReleaseFastMutexUnsafe((_hive_)->HiveLock)

Definition at line 662 of file cmp.h.

Referenced by CmFlushKey(), CmpCloseKeyObject(), CmpDoFlushAll(), and CmpFlushNotify().

#define DCmCheckRegistry | ( | a |  | ) |

| Definition at line 308 of file cmp.h. Referenced by CmFlushKey(), CmpSetSecurityDescriptorInfo(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

#define DELIST_KEYBODY_FROM_KEYBODY_LIST | ( | KeyBody |  | ) |

| Definition at line 527 of file cmp.h. Referenced by CmpDeleteKeyObject().

#define END_LOCK_CHECKPOINT

Value:

    } except(CmpCheckLockExceptionFilter(GetExceptionInformation())) {}     \
            LockCountAfter = ExIsResourceAcquiredShared(&CmpRegistryLock);          \
            LockCountAfter += ExIsResourceAcquiredExclusive(&CmpRegistryLock);      \
            if( LockCountBefore != LockCountAfter ) {                               \
                KeBugCheckEx(REGISTRY_ERROR,13,LockCountBefore,LockCountAfter,0);   \
            }                                                                       \
        }

Definition at line 325 of file cmp.h.

Referenced by NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtLoadKey2(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryOpenSubKeys(), NtQueryValueKey(), NtReplaceKey(), NtRestoreKey(), NtSaveKey(), NtSaveMergedKeys(), NtSetInformationKey(), NtSetValueKey(), and NtUnloadKey().

#define EndWmiCmTrace | ( | Status,
|  | Handle,
|  | KeyName,
|  | Type |  | ) |

Value:

    if (CmpTraceRoutine) {\
            try {\
                if (WmiUsePerfClock) {\
                    EndSystemTime = KeQueryPerformanceCounter(NULL);\
                }\
                else {\
                    KeQuerySystemTime(&EndSystemTime);\
                }\
                CmpWmiFireEvent(Status,Handle,EndSystemTime.QuadPart - StartSystemTime.QuadPart,KeyName,Type);\
            } except (EXCEPTION_EXECUTE_HANDLER) {\
            }\
        }

Definition at line 97 of file cmp.h.

Referenced by NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryValueKey(), NtSetInformationKey(), and NtSetValueKey().

#define ENLIST_KEYBODY_IN_KEYBODY_LIST | ( | KeyBody |  | ) |

| Definition at line 526 of file cmp.h. Referenced by CmpCreateRegistryRoot(), CmpDoCreateChild(), and CmpDoOpen().

#define GET_HASH_ENTRY | ( | Table,
|  | Key |  | ) | Table[GET_HASH_INDEX(Key)]

| Definition at line 475 of file cmp.h. Referenced by CmpCacheLookup(), CmpDereferenceNameControlBlockWithLock(), and CmpGetSymbolicLink().

#define GET_HASH_INDEX | ( | Key |  | ) | HASH_KEY(Key) % CmpHashTableSize

| Definition at line 474 of file cmp.h. Referenced by CmpGetNameControlBlock(), and CmpInsertKeyHash().

#define HASH_KEY | ( | _convkey_ |  | ) | ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)

| Definition at line 472 of file cmp.h. Referenced by CmpRemoveKeyHash().

#define HvpChangeBinAllocation | ( | a,
|  | b |  | ) |

| Definition at line 170 of file cmp.h.

#define HvpMarkBinReadWrite | ( | a,
|  | b |  | ) |

| Definition at line 171 of file cmp.h. Referenced by HvMarkDirty().

#define INIT_KCB_KEYBODY_LIST | ( | kcb |  | ) |

| Definition at line 524 of file cmp.h. Referenced by CmpCreateKeyControlBlock().

#define IsMasterPostBlock | ( | _post_ |  | ) | ( ((_post_)->NotifyType) & REG_NOTIFY_MASTER_POST )

| Definition at line 632 of file cmp.h. Referenced by CmNotifyRunDown(), CmpAllocatePostBlock(), CmpCancelSlavePost(), CmpFreePostBlock(), CmpFreeSlavePost(), CmpNotifyChangeKey(), and CmpPostNotify().

#define KCB_WORKER_CONTINUE 0

| Definition at line 855 of file cmp.h. Referenced by CmpRefreshWorkerRoutine(), and CmpSearchKeyControlBlockTree().

#define KCB_WORKER_DELETE 2

| Definition at line 857 of file cmp.h. Referenced by CmpRefreshWorkerRoutine(), and CmpSearchKeyControlBlockTree().

#define KCB_WORKER_DONE 1

| Definition at line 856 of file cmp.h. Referenced by CmpSearchKeyControlBlockTree().

#define KEY_BODY_TYPE 0x6b793032

| Definition at line 486 of file cmp.h. Referenced by CmpCloseKeyObject(), CmpCreateRegistryRoot(), CmpDelayedDerefKeys(), CmpDeleteKeyObject(), CmpDoCreateChild(), and CmpDoOpen().

#define LOCK_KCB_TREE | (

)

ExAcquireFastMutexUnsafe(&CmpKcbLock)

| Definition at line 230 of file cmp.h. Referenced by CmEnumerateValueKey(), CmpAddInfoAfterParseFailure(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlock(), CmpDoOpen(), CmpGetSymbolicLink(), CmpParseKey(), and CmQueryValueKey().

#define LOCK_POST_LIST | (

)

ExAcquireFastMutexUnsafe(&CmpPostLock)

| Definition at line 643 of file cmp.h. Referenced by CmpPostNotify().

#define MAX_HIVE_LAYERS 2

| Definition at line 442 of file cmp.h.

#define NUMBER_TYPES (MaximumType + 1)

| Definition at line 420 of file cmp.h. Referenced by CmpInitializeMachineDependentConfiguration(), and CmpSetupConfigurationTree().

#define PostBlockType | ( | _post_ |  | ) | ((POST_BLOCK_TYPE)( ((_post_)->NotifyType) & REG_NOTIFY_POST_TYPE_MASK ))

| Definition at line 630 of file cmp.h. Referenced by CmNotifyRunDown(), CmpFreePostBlock(), CmpNotifyTriggerCheck(), and CmpPostNotify().

#define REG_CMD_ADD_HIVE_LIST 8

| Definition at line 726 of file cmp.h. Referenced by CmLoadKey(), CmpLoadHiveVolatile(), and CmpWorker().

#define REG_CMD_FILE_SET_SIZE 3

| Definition at line 721 of file cmp.h. Referenced by CmpFileSetSize(), CmpWorker(), and CmpWorkerCommand().

#define REG_CMD_FLUSH_KEY 2

| Definition at line 720 of file cmp.h. Referenced by CmpWorker(), CmpWorkerCommand(), CmUnloadKey(), and NtFlushKey().

#define REG_CMD_HIVE_CLOSE 5

| Definition at line 723 of file cmp.h. Referenced by CmLoadKey(), CmpWorker(), CmpWorkerCommand(), CmReplaceKey(), and CmUnloadKey().

#define REG_CMD_HIVE_OPEN 4

| Definition at line 722 of file cmp.h. Referenced by CmLoadKey(), CmpWorker(), CmpWorkerCommand(), and CmReplaceKey().

#define REG_CMD_HIVE_READ 11

| Definition at line 729 of file cmp.h. Referenced by CmpSaveKeyByFileCopy(), and CmpWorker().

#define REG_CMD_INIT 1

| Definition at line 719 of file cmp.h. Referenced by CmpWorker(), and NtInitializeRegistry().

#define REG_CMD_REFRESH_HIVE 10

| Definition at line 728 of file cmp.h. Referenced by CmpRefreshHive(), and CmpWorker().

#define REG_CMD_REMOVE_HIVE_LIST 9

| Definition at line 727 of file cmp.h. Referenced by CmpWorker(), and CmUnloadKey().

#define REG_CMD_RENAME_HIVE 7

| Definition at line 725 of file cmp.h. Referenced by CmpWorker(), and CmReplaceKey().

#define REG_CMD_SHUTDOWN 6

| Definition at line 724 of file cmp.h. Referenced by CmpWorker(), CmpWorkerCommand(), and CmShutdownSystem().

#define REG_NOTIFY_MASTER_POST (0x00010000L)

| Definition at line 625 of file cmp.h. Referenced by CmpFreePostBlock().

#define REG_NOTIFY_POST_TYPE_MASK (0x0000FFFFL)

| Definition at line 623 of file cmp.h.

#define REG_OPTION_PREDEF_HANDLE (0x00000008L)

| Definition at line 766 of file cmp.h. Referenced by CmpCreatePredefined(), and CmpDoCreateChild().

#define REG_PREDEF_HANDLE_MASK (0x80000000L)

| Definition at line 767 of file cmp.h. Referenced by CmpDeleteKeyObject().

#define REGCHECKING 1

| Definition at line 297 of file cmp.h.

#define REGISTRY_LOCK_CHECKING

| Definition at line 311 of file cmp.h.

#define RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */

| Definition at line 469 of file cmp.h.

#define RNDM_PRIME 1000000007 /* prime number, also used for scrambling */

| Definition at line 470 of file cmp.h.

#define SetMasterPostBlockFlag | ( | _post_ |  | ) | ( ((_post_)->NotifyType) |= REG_NOTIFY_MASTER_POST )

| Definition at line 633 of file cmp.h. Referenced by CmpPostNotify().

#define SetUsed | ( | Hive,
|  | Cell |  | ) |

Value:

    {                                               \
            PCELL_DATA  p;                              \
            p = HvGetCell(Hive, Cell);                  \
            CmpUsedStorage += HvGetCellSize(Hive, p);   \
        }

Definition at line 1555 of file cmp.h.

Referenced by CmpCheckKey(), CmpCheckValueList(), and CmpValidateHiveSecurityDescriptors().

#define StartWmiCmTrace | (

)

Value:

    LARGE_INTEGER StartSystemTime;\
        LARGE_INTEGER EndSystemTime;\
        if (CmpTraceRoutine) {\
            if (WmiUsePerfClock) {\
                StartSystemTime = KeQueryPerformanceCounter(NULL);\
            }\
            else {\
                KeQuerySystemTime(&StartSystemTime);\
            }\
        }

Definition at line 84 of file cmp.h.

Referenced by NtCreateKey(), NtDeleteKey(), NtDeleteValueKey(), NtEnumerateKey(), NtEnumerateValueKey(), NtFlushKey(), NtOpenKey(), NtQueryKey(), NtQueryMultipleValueKey(), NtQueryValueKey(), NtSetInformationKey(), and NtSetValueKey().

#define UNLOCK_KCB_TREE | (

)

ExReleaseFastMutexUnsafe(&CmpKcbLock)

| Definition at line 231 of file cmp.h. Referenced by CmEnumerateValueKey(), CmpAddInfoAfterParseFailure(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlock(), CmpDoOpen(), CmpGetSymbolicLink(), CmpParseKey(), and CmQueryValueKey().

#define UNLOCK_POST_LIST | (

)

ExReleaseFastMutexUnsafe(&CmpPostLock)

| Definition at line 644 of file cmp.h. Referenced by CmpPostNotify().

#define VALIDATE_CELL_MAP | ( | LINE,
|  | Map,
|  | Hive,
|  | Address |  | ) |

Value:

    if( Map == NULL ) {                                                                             \
                CM_BUGCHECK (REGISTRY_ERROR,11,(ULONG_PTR)(Hive),(ULONG)(Address),(ULONG)(LINE)) ;     \
        }

Definition at line 378 of file cmp.h.

Referenced by HvFreeCell(), HvFreeHive(), HvFreeHivePartial(), HvIsBinDirty(), HvMarkCellDirty(), HvpAddBin(), HvpBuildMapAndCopy(), HvpCoalesceDiscardedBins(), HvpDiscardBins(), HvpDoWriteHive(), HvpEnlistBinInMap(), HvpFindNextDirtyBlock(), HvpRecoverData(), HvpTruncateBins(), and HvRefreshHive().

## Typedef Documentation

typedef struct _BOOT_DRIVER_NODE BOOT_DRIVER_NODE

| Referenced by CmpFindDrivers().

typedef struct _CM_ASYNC_KERNEL_POST_BLOCK CM_ASYNC_KERNEL_POST_BLOCK

typedef struct _CM_ASYNC_USER_POST_BLOCK CM_ASYNC_USER_POST_BLOCK

typedef struct _CM_HARDWARE_PROFILE CM_HARDWARE_PROFILE

| Referenced by CmpFindProfileOption().

typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS CM_HARDWARE_PROFILE_ACPI_ALIAS

typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST

typedef struct _CM_HARDWARE_PROFILE_ALIAS CM_HARDWARE_PROFILE_ALIAS

typedef struct _CM_HARDWARE_PROFILE_ALIAS_LIST CM_HARDWARE_PROFILE_ALIAS_LIST

typedef struct _CM_HARDWARE_PROFILE_LIST CM_HARDWARE_PROFILE_LIST

| Referenced by CmpFindProfileOption().

typedef struct _CM_KEY_BODY CM_KEY_BODY

typedef struct _CM_NOTIFY_BLOCK CM_NOTIFY_BLOCK

| Referenced by CmpNotifyChangeKey(), and CmpReportNotifyHelper().

typedef struct _CM_PARSE_CONTEXT CM_PARSE_CONTEXT

| Referenced by NtCreateKey().

typedef struct _CM_POST_BLOCK CM_POST_BLOCK

| Referenced by CmpAllocatePostBlock(), CmpFreePostBlock(), and CmpNotifyTriggerCheck().

typedef union _CM_POST_BLOCK_UNION CM_POST_BLOCK_UNION

| Referenced by CmpAllocatePostBlock().

typedef struct _CM_POST_KEY_BODY CM_POST_KEY_BODY

| Referenced by CmpAllocatePostBlock(), and CmpDelayedDerefKeys().

typedef struct _CM_SYNC_POST_BLOCK CM_SYNC_POST_BLOCK

typedef struct _CMHIVE CMHIVE

| Referenced by CmFlushKey(), CmpInitializeHive(), and pool().

typedef struct _HIVE_LIST_ENTRY HIVE_LIST_ENTRY

typedef struct _BOOT_DRIVER_NODE * PBOOT_DRIVER_NODE

typedef NTSTATUS(* PCM_ACPI_SELECTION_ROUTINE)(IN PCM_HARDWARE_PROFILE_LIST ProfileList, OUT PULONG ProfileIndexToUse,IN PVOID Context)

| Definition at line 1798 of file cmp.h.

typedef struct _CM_ASYNC_KERNEL_POST_BLOCK * PCM_ASYNC_KERNEL_POST_BLOCK

typedef struct _CM_ASYNC_USER_POST_BLOCK * PCM_ASYNC_USER_POST_BLOCK

typedef struct _CM_HARDWARE_PROFILE * PCM_HARDWARE_PROFILE

| Referenced by CmpSetCurrentProfile().

typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS * PCM_HARDWARE_PROFILE_ACPI_ALIAS

typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST * PCM_HARDWARE_PROFILE_ACPI_ALIAS_LIST

typedef struct _CM_HARDWARE_PROFILE_ALIAS * PCM_HARDWARE_PROFILE_ALIAS

typedef struct _CM_HARDWARE_PROFILE_ALIAS_LIST * PCM_HARDWARE_PROFILE_ALIAS_LIST

| Referenced by CmpFindProfileOption().

typedef struct _CM_HARDWARE_PROFILE_LIST * PCM_HARDWARE_PROFILE_LIST

| Referenced by CmpFindProfileOption().

typedef struct _CM_KEY_BODY * PCM_KEY_BODY

| Referenced by CmDeleteKey().

typedef struct _CM_NOTIFY_BLOCK * PCM_NOTIFY_BLOCK

| Referenced by CmpCloseKeyObject().

typedef struct _CM_PARSE_CONTEXT * PCM_PARSE_CONTEXT

typedef struct _CM_POST_BLOCK * PCM_POST_BLOCK

| Referenced by NtNotifyChangeMultipleKeys().

typedef union _CM_POST_BLOCK_UNION * PCM_POST_BLOCK_UNION

typedef struct _CM_POST_KEY_BODY * PCM_POST_KEY_BODY

| Referenced by CmpDelayedDerefKeys().

typedef struct _CM_SYNC_POST_BLOCK * PCM_SYNC_POST_BLOCK

typedef struct _CMHIVE * PCMHIVE

| Referenced by CmFlushKey().

typedef struct _HIVE_LIST_ENTRY * PHIVE_LIST_ENTRY

| Referenced by pool().

typedef ULONG(* PKCB_WORKER_ROUTINE)(PCM_KEY_CONTROL_BLOCK Current, PVOID Context1, PVOID Context2)

| Definition at line 861 of file cmp.h.

typedef enum _POST_BLOCK_TYPE POST_BLOCK_TYPE

| Referenced by CmpNotifyTriggerCheck(), and NtNotifyChangeMultipleKeys().

typedef struct _REGISTRY_COMMAND * PREGISTRY_COMMAND

typedef struct _REGISTRY_COMMAND REGISTRY_COMMAND

| Referenced by CmLoadKey(), and NtFlushKey().

## Enumeration Type Documentation

enum _POST_BLOCK_TYPE

Enumeration values:

  PostSynchronous |
  PostAsyncUser |
  PostAsyncKernel |

Definition at line 582 of file cmp.h.

    00582                               {
    00583     PostSynchronous = 1,
    00584     PostAsyncUser = 2,
    00585     PostAsyncKernel = 3
    00586 } POST_BLOCK_TYPE;

## Function Documentation

ULONG CmCheckRegistry | ( | PCMHIVE | CmHive,
|  | BOOLEAN | Clean
| ) |

Definition at line 108 of file cmchek.c.

References _HHIVE::BaseBlock, CmCheckRegistryDebug, CmpCheckClean, CmpCheckHive, CmpCheckRegistry2(), CmpMasterHive, CmpUsedStorage, CmpValidateHiveSecurityDescriptors(), HCELL_NIL, _CMHIVE::Hive, Hive, HvCheckHive(), _HBASE_BLOCK::RootCell, and UsedStorage.

Referenced by CmpInitializeHive(), CmpInitializeSystemHive(), and HvRefreshHive().

    00114                    :
    00115
    00116     Check consistency of the registry within a given hive.  Start from
    00117     root, and check that:
    00118         .   Each child key points back to its parent.
    00119         .   All allocated cells are refered to exactly once
    00120             (requires looking inside the hive structure...)
    00121             [This also detects space leaks.]
    00122         .   All allocated cells are reachable from the root.
    00123
    00124     NOTE:   Exactly 1 ref rule may change with security.
    00125
    00126 Arguments:
    00127
    00128     CmHive - supplies a pointer to the CM hive control structure for the
    00129             hive of interest.
    00130
    00131     Clean   - if TRUE, references to volatile cells will be zapped
    00132               (done at startup only to avoid groveling hives twice.)
    00133               if FALSE, nothing will be changed.
    00134
    00135 Return Value:
    00136
    00137     0 if Hive is OK.  Error return indicator if not.
    00138
    00139     RANGE:  3000 - 3999
    00140
    00141 --*/
    00142 {
    00143     PHHIVE  Hive;
    00144     ULONG   rc = 0;
    00145     ULONG   Storage;
    00146
    00147     if (CmHive == CmpMasterHive) {
    00148         return(0);
    00149     }
    00150
    00151     CmpUsedStorage = 0;
    00152
    00153     CmCheckRegistryDebug.Hive = (PHHIVE)CmHive;
    00154     CmCheckRegistryDebug.Status = 0;
    00155
    00156
    00157     //
    00158     // check the underlying hive and get storage use
    00159     //
    00160     Hive = &CmHive->Hive;
    00161
    00162     rc = HvCheckHive(Hive, &Storage);
    00163     if (rc != 0) {
    00164         CmCheckRegistryDebug.Status = rc;
    00165         return rc;
    00166     }
    00167
    00168     //
    00169     // Call recursive helper to check out the values and subkeys
    00170     //
    00171     CmpCheckHive = (PHHIVE)CmHive;
    00172     CmpCheckClean = Clean;
    00173     rc = CmpCheckRegistry2(Hive->BaseBlock->RootCell, HCELL_NIL);
    00174
    00175     //
    00176     // Validate all the security descriptors in the hive
    00177     //
    00178     if (!CmpValidateHiveSecurityDescriptors(Hive)) {
    00179         KdPrint(("CmCheckRegistry:"));
    00180         KdPrint((" CmpValidateHiveSecurityDescriptors failed\n"));
    00181         rc = 3040;
    00182         CmCheckRegistryDebug.Status = rc;
    00183     }
    00184
    00185 #if 0
    00186     //
    00187     // Check allocated storage against used storage
    00188     //
    00189     if (CmpUsedStorage != Storage) {
    00190         KdPrint(("CmCheckRegistry:"));
    00191         KdPrint((" Storage Used:%08lx  Allocated:%08lx\n", UsedStorage, Storage));
    00192         rc = 3042;
    00193         CmCheckRegistryDebug.Status = rc;
    00194     }
    00195 #endif
    00196
    00197     //
    00198     // Print a bit of a summary (make sure this data avail in all error cases)
    00199     //
    00200     if (rc > 0) {
    00201         KdPrint(("CmCheckRegistry Failed (%d): CmHive:%08lx\n", rc, CmHive));
    00202         KdPrint((" Hive:%08lx Root:%08lx\n", Hive, Hive->BaseBlock->RootCell));
    00203     }
    00204
    00205     return rc;
    00206 }

NTSTATUS CmDeleteKey | ( | IN PCM_KEY_BODY | KeyBody | ) |

Definition at line 31 of file cmapi2.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CML_WORKER, CMLOG, CmpCleanUpSubKeyInfo(), CmpFlushNotify(), CmpFreeKeyByCell(), CmpLockRegistryExclusive(), CmpMarkAllBinsReadOnly, CmpRemoveKeyControlBlock(), CmpReportNotify(), CmpUnlockRegistry(), CMS_CM, _CM_KEY_CONTROL_BLOCK::Delete, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, Hive, KEY_NO_DELETE, _CM_KEY_CONTROL_BLOCK::KeyCell, _CM_KEY_CONTROL_BLOCK::KeyHive, _CM_KEY_CONTROL_BLOCK::KeyNode, NT_SUCCESS, NTSTATUS(), NULL, _CM_KEY_CONTROL_BLOCK::ParentKcb, PCM_KEY_BODY, Stable, _CM_KEY_NODE::SubKeyCounts, TRUE, and Volatile.

Referenced by NtDeleteKey().

    00036                    :
    00037
    00038     Delete a registry key, clean up Notify block.
    00039
    00040 Arguments:
    00041
    00042     KeyBody - pointer to key handle object
    00043
    00044 Return Value:
    00045
    00046     NTSTATUS
    00047
    00048 --*/
    00049 {
    00050     NTSTATUS    status;
    00051     PCM_KEY_NODE  ptarget;
    00052     PHHIVE      Hive;
    00053     HCELL_INDEX Cell;
    00054     PCM_KEY_CONTROL_BLOCK   KeyControlBlock;
    00055
    00056     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmDeleteKey\n"));
    00057
    00058     CmpLockRegistryExclusive();
    00059
    00060     //
    00061     // If already marked for deletion, storage is gone, so
    00062     // do nothing and return success.
    00063     //
    00064     KeyControlBlock = KeyBody->KeyControlBlock;
    00065
    00066     if (KeyControlBlock->Delete == TRUE) {
    00067         status = STATUS_SUCCESS;
    00068         goto Exit;
    00069     }
    00070
    00071     // Mark the hive as read only
    00072     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00073
    00074     ptarget = KeyControlBlock->KeyNode;
    00075
    00076     if ( ((ptarget->SubKeyCounts[Stable] +
    00077            ptarget->SubKeyCounts[Volatile]) == 0) &&
    00078          ((ptarget->Flags & KEY_NO_DELETE) == 0))
    00079     {
    00080         //
    00081         // Cell is NOT marked NO_DELETE and does NOT have children
    00082         // Send Notification while key still present, if delete fails,
    00083         //   we'll have sent a spurious notify, that doesn't matter
    00084         // Delete the actual storage
    00085         //
    00086         Hive = KeyControlBlock->KeyHive;
    00087         Cell = KeyControlBlock->KeyCell;
    00088
    00089         CmpReportNotify(
    00090             KeyControlBlock,
    00091             Hive,
    00092             Cell,
    00093             REG_NOTIFY_CHANGE_NAME
    00094             );
    00095
    00096         status = CmpFreeKeyByCell(Hive, Cell, TRUE);
    00097
    00098         if (NT_SUCCESS(status)) {
    00099             //
    00100             // post any waiting notifies
    00101             //
    00102 #ifdef KCB_TO_KEYBODY_LINK
    00103             CmpFlushNotifiesOnKeyBodyList(KeyControlBlock);
    00104 #else
    00105             CmpFlushNotify(KeyBody);
    00106 #endif
    00107
    00108             //
    00109             // Remove kcb out of cache, but do NOT
    00110             // free its storage, CmDelete will do that when
    00111             // the RefCount becomes zero.
    00112             //
    00113             // There are two things that can hold the RefCount non-zero.
    00114             //
    00115             // 1. open handles for this key
    00116             // 2. Fake subKeys that are still in DelayClose.
    00117             //
    00118             // At this point, we have no way of deleting the fake subkeys from cache
    00119             // unless we do a search for the whole cache, which is too expensive.
    00120             // Thus, we decide to either let the fake keys age out of cache or when
    00121             // someone is doing the lookup for the fake key, then we delete it at that point.
    00122             // See routine CmpCacheLookup in cmparse.c for more details.
    00123             //
    00124             // If the parent has the subkey info or hint cached, free it.
    00125             // Again, registry is locked exclusively, no need to lock KCB.
    00126             //
    00127             ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00128             CmpCleanUpSubKeyInfo(KeyControlBlock->ParentKcb);
    00129             KeyControlBlock->Delete = TRUE;
    00130             CmpRemoveKeyControlBlock(KeyControlBlock);
    00131             KeyControlBlock->KeyCell = HCELL_NIL;
    00132             KeyControlBlock->KeyNode = NULL;
    00133         }
    00134
    00135     } else {
    00136
    00137         status = STATUS_CANNOT_DELETE;
    00138
    00139     }
    00140
    00141 Exit:
    00142     CmpUnlockRegistry();
    00143
    00144     // Mark the hive as read only
    00145     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00146
    00147     return status;
    00148 }
    }

NTSTATUS CmDeleteValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN UNICODE_STRING | ValueName
| ) |

Definition at line 92 of file cmapi.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CML_WORKER, CMLOG, CmpCleanUpKcbValueCache(), CmpFindNameInList(), CmpFreeValue(), CmpIsHKeyValueSmall, CmpLockRegistryExclusive(), CmpMarkAllBinsReadOnly, CmpReportNotify(), CmpUnlockRegistry(), CMS_CM, _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, HCELL_INDEX, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, HvMarkCellDirty(), HvReallocateCell(), KeQuerySystemTime(), _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyValue, _CM_KEY_NODE::LastWriteTime, _CHILD_LIST::List, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, NTSTATUS(), PCHILD_LIST, PCM_KEY_CONTROL_BLOCK, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and ValueName.

Referenced by EhDeleteValueKey(), and NtDeleteValueKey().

    00098                    :
    00099
    00100     One of the value entries of a registry key may be removed with this call.
    00101
    00102     The value entry with ValueName matching ValueName is removed from the key.
    00103     If no such entry exists, an error is returned.
    00104
    00105 Arguments:
    00106
    00107     KeyControlBlock - pointer to kcb for key to operate on
    00108
    00109     ValueName - The name of the value to be deleted.  NULL is a legal name.
    00110
    00111 Return Value:
    00112
    00113     NTSTATUS - Result code from call, among the following:
    00114
    00115         <TBS>
    00116
    00117 --*/
    00118 {
    00119     NTSTATUS status;
    00120     PCM_KEY_NODE pcell;
    00121     PCHILD_LIST plist;
    00122     PCELL_DATA targetaddress;
    00123     ULONG  targetindex;
    00124     ULONG   newcount;
    00125     HCELL_INDEX newcell;
    00126     HCELL_INDEX ChildCell;
    00127     PHHIVE      Hive;
    00128     HCELL_INDEX Cell;
    00129     ULONG realsize;
    00130     LARGE_INTEGER systemtime;
    00131
    00132     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmDeleteValueKey\n"));
    00133
    00134     CmpLockRegistryExclusive();
    00135
    00136     try {
    00137         //
    00138         // no edits, not even this one, on keys marked for deletion
    00139         //
    00140         if (KeyControlBlock->Delete) {
    00141             return STATUS_KEY_DELETED;
    00142         }
    00143
    00144         Hive = KeyControlBlock->KeyHive;
    00145         Cell = KeyControlBlock->KeyCell;
    00146         pcell = KeyControlBlock->KeyNode;
    00147
    00148         // Mark the hive as read only
    00149         CmpMarkAllBinsReadOnly(Hive);
    00150
    00151         status = STATUS_OBJECT_NAME_NOT_FOUND;
    00152
    00153         plist = &(pcell->ValueList);
    00154         ChildCell = HCELL_NIL;
    00155
    00156         if (plist->Count != 0) {
    00157
    00158             //
    00159             // The parent has at least one value, map in the list of
    00160             // values and call CmpFindChildInList
    00161             //
    00162
    00163             //
    00164             // plist -> the CHILD_LIST structure
    00165             // pchild -> the child node structure being examined
    00166             //
    00167
    00168             ChildCell = CmpFindNameInList(Hive,
    00169                                           plist,
    00170                                           &ValueName,
    00171                                           &targetaddress,
    00172                                           &targetindex);
    00173
    00174             if (ChildCell != HCELL_NIL) {
    00175
    00176                 //
    00177                 // 1. the desired target was found
    00178                 // 2. ChildCell is it's HCELL_INDEX
    00179                 // 3. targetaddress points to it
    00180                 // 4. targetindex is it's index
    00181                 //
    00182
    00183                 //
    00184                 // attempt to mark all relevent cells dirty
    00185                 //
    00186                 if (!(HvMarkCellDirty(Hive, Cell) &&
    00187                       HvMarkCellDirty(Hive, pcell->ValueList.List) &&
    00188                       HvMarkCellDirty(Hive, ChildCell)))
    00189
    00190                 {
    00191                     // Mark the hive as read only
    00192                     CmpMarkAllBinsReadOnly(Hive);
    00193
    00194                     return STATUS_NO_LOG_SPACE;
    00195                 }
    00196
    00197                 if (!CmpIsHKeyValueSmall(realsize,targetaddress->u.KeyValue.DataLength)) {
    00198
    00199                     if (!HvMarkCellDirty(Hive, targetaddress->u.KeyValue.Data)) {
    00200
    00201                         // Mark the hive as read only
    00202                         CmpMarkAllBinsReadOnly(Hive);
    00203
    00204                         return(STATUS_NO_LOG_SPACE);
    00205                     }
    00206                 }
    00207
    00208                 newcount = plist->Count - 1;
    00209
    00210                 if (newcount > 0) {
    00211                     PCELL_DATA pvector;
    00212
    00213                     //
    00214                     // more than one entry list, squeeze
    00215                     //
    00216                     pvector = HvGetCell(Hive, plist->List);
    00217                     for ( ; targetindex < newcount; targetindex++) {
    00218                         pvector->u.KeyList[ targetindex ] =
    00219                             pvector->u.KeyList[ targetindex+1 ];
    00220                     }
    00221
    00222                     newcell = HvReallocateCell(
    00223                                 Hive,
    00224                                 plist->List,
    00225                                 newcount * sizeof(HCELL_INDEX)
    00226                                 );
    00227                     ASSERT(newcell != HCELL_NIL);
    00228                     plist->List = newcell;
    00229
    00230                 } else {
    00231
    00232                     //
    00233                     // list is empty, free it
    00234                     //
    00235                     HvFreeCell(Hive, plist->List);
    00236                 }
    00237                 plist->Count = newcount;
    00238                 CmpFreeValue(Hive, ChildCell);
    00239
    00240                 KeQuerySystemTime(&systemtime);
    00241                 pcell->LastWriteTime = systemtime;
    00242
    00243                 if (pcell->ValueList.Count == 0) {
    00244                     pcell->MaxValueNameLen = 0;
    00245                     pcell->MaxValueDataLen = 0;
    00246                 }
    00247
    00248                 //
    00249                 // We are changing the KCB cache. Since the registry is locked exclusively,
    00250                 // we do not need a KCB lock.
    00251                 //
    00252                 ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00253
    00254                 //
    00255                 // Invalidate the cache
    00256                 //
    00257                 CmpCleanUpKcbValueCache(KeyControlBlock);
    00258
    00259                 KeyControlBlock->ValueCache.Count = plist->Count;
    00260                 KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) plist->List;
    00261
    00262                 CmpReportNotify(
    00263                         KeyControlBlock,
    00264                         KeyControlBlock->KeyHive,
    00265                         KeyControlBlock->KeyCell,
    00266                         REG_NOTIFY_CHANGE_LAST_SET
    00267                         );
    00268                 status = STATUS_SUCCESS;
    00269             } else {
    00270                 status = STATUS_OBJECT_NAME_NOT_FOUND;
    00271             }
    00272         }
    00273     } finally {
    00274         CmpUnlockRegistry();
    00275     }
    00276
    00277     // Mark the hive as read only
    00278     CmpMarkAllBinsReadOnly(Hive);
    00279
    00280     return status;
    00281 }

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

Definition at line 285 of file cmapi.c.

References Cell, CML_WORKER, CMLOG, CmpFindSubKeyByNumber(), CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpQueryKeyData(), CmpUnlockRegistry(), CMS_CM, EXCEPTION_EXECUTE_HANDLER, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, Index, and NTSTATUS().

Referenced by EhEnumerateKey(), and NtEnumerateKey().

    00295                    :
    00296
    00297     Enumerate sub keys, return data on Index'th entry.
    00298
    00299     CmEnumerateKey returns the name of the Index'th sub key of the open
    00300     key specified.  The value STATUS_NO_MORE_ENTRIES will be
    00301     returned if value of Index is larger than the number of sub keys.
    00302
    00303     Note that Index is simply a way to select among child keys.  Two calls
    00304     to CmEnumerateKey with the same Index are NOT guaranteed to return
    00305     the same results.
    00306
    00307     If KeyInformation is not long enough to hold all requested data,
    00308     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00309     set to the number of bytes actually required.
    00310
    00311 Arguments:
    00312
    00313     KeyControlBlock - pointer to the KCB that describes the key
    00314
    00315     Index - Specifies the (0-based) number of the sub key to be returned.
    00316
    00317     KeyInformationClass - Specifies the type of information returned in
    00318         Buffer.  One of the following types:
    00319
    00320         KeyBasicInformation - return last write time, title index, and name.
    00321             (see KEY_BASIC_INFORMATION structure)
    00322
    00323         KeyNodeInformation - return last write time, title index, name, class.
    00324             (see KEY_NODE_INFORMATION structure)
    00325
    00326     KeyInformation -Supplies pointer to buffer to receive the data.
    00327
    00328     Length - Length of KeyInformation in bytes.
    00329
    00330     ResultLength - Number of bytes actually written into KeyInformation.
    00331
    00332 Return Value:
    00333
    00334     NTSTATUS - Result code from call, among the following:
    00335
    00336         <TBS>
    00337
    00338 --*/
    00339 {
    00340     NTSTATUS    status;
    00341     HCELL_INDEX childcell;
    00342     PHHIVE Hive;
    00343     HCELL_INDEX Cell;
    00344     PCM_KEY_NODE Node;
    00345
    00346     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmEnumerateKey\n"));
    00347
    00348
    00349     CmpLockRegistry();
    00350
    00351     if (KeyControlBlock->Delete) {
    00352         CmpUnlockRegistry();
    00353         return STATUS_KEY_DELETED;
    00354     }
    00355
    00356     Hive = KeyControlBlock->KeyHive;
    00357     Cell = KeyControlBlock->KeyCell;
    00358
    00359     // Mark the hive as read only
    00360     CmpMarkAllBinsReadOnly(Hive);
    00361
    00362     //
    00363     // fetch the child of interest
    00364     //
    00365
    00366     childcell = CmpFindSubKeyByNumber(Hive, KeyControlBlock->KeyNode, Index);
    00367     if (childcell == HCELL_NIL) {
    00368         //
    00369         // no such child, clean up and return error
    00370         //
    00371
    00372         CmpUnlockRegistry();
    00373
    00374         // Mark the hive as read only
    00375         CmpMarkAllBinsReadOnly(Hive);
    00376
    00377         return STATUS_NO_MORE_ENTRIES;
    00378     }
    00379
    00380     Node = (PCM_KEY_NODE)HvGetCell(Hive,childcell);
    00381
    00382     try {
    00383
    00384         //
    00385         // call a worker to perform data transfer
    00386         //
    00387
    00388         status = CmpQueryKeyData(Hive,
    00389                                  Node,
    00390                                  KeyInformationClass,
    00391                                  KeyInformation,
    00392                                  Length,
    00393                                  ResultLength);
    00394
    00395      } except (EXCEPTION_EXECUTE_HANDLER) {
    00396         CmpUnlockRegistry();
    00397         status = GetExceptionCode();
    00398
    00399         // Mark the hive as read only
    00400         CmpMarkAllBinsReadOnly(Hive);
    00401
    00402         return status;
    00403     }
    00404
    00405     CmpUnlockRegistry();
    00406
    00407     // Mark the hive as read only
    00408     CmpMarkAllBinsReadOnly(Hive);
    00409
    00410     return status;
    00411 }

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

Definition at line 416 of file cmapi.c.

References CM_KCB_SYM_LINK_FOUND, CML_WORKER, CMLOG, CMP_GET_CACHED_ADDRESS, CmpDereferenceKeyControlBlockWithLock(), CmpGetValueKeyFromCache(), CmpGetValueListFromCache(), CmpLockRegistry(), CmpMakeValueCacheReadOnly, CmpMakeValueCacheReadWrite, CmpMarkAllBinsReadOnly, CmpQueryKeyValueData(), CmpUnlockRegistry(), CMS_CM, Hive, Index, LOCK_KCB_TREE, NTSTATUS(), PCM_KEY_VALUE, PPCM_CACHED_VALUE, and UNLOCK_KCB_TREE.

Referenced by EhEnumerateValueKey(), and NtEnumerateValueKey().

    00426                    :
    00427
    00428     The value entries of an open key may be enumerated.
    00429
    00430     CmEnumerateValueKey returns the name of the Index'th value
    00431     entry of the open key specified by KeyHandle.  The value
    00432     STATUS_NO_MORE_ENTRIES will be returned if value of Index is
    00433     larger than the number of sub keys.
    00434
    00435     Note that Index is simply a way to select among value
    00436     entries.  Two calls to NtEnumerateValueKey with the same Index
    00437     are NOT guaranteed to return the same results.
    00438
    00439     If KeyValueInformation is not long enough to hold all requested data,
    00440     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00441     set to the number of bytes actually required.
    00442
    00443 Arguments:
    00444
    00445     KeyControlBlock - pointer to the KCB that describes the key
    00446
    00447     Index - Specifies the (0-based) number of the sub key to be returned.
    00448
    00449     KeyValueInformationClass - Specifies the type of information returned
    00450     in Buffer. One of the following types:
    00451
    00452         KeyValueBasicInformation - return time of last write,
    00453             title index, and name.  (See KEY_VALUE_BASIC_INFORMATION)
    00454
    00455         KeyValueFullInformation - return time of last write,
    00456             title index, name, class.  (See KEY_VALUE_FULL_INFORMATION)
    00457
    00458     KeyValueInformation -Supplies pointer to buffer to receive the data.
    00459
    00460     Length - Length of KeyValueInformation in bytes.
    00461
    00462     ResultLength - Number of bytes actually written into KeyValueInformation.
    00463
    00464 Return Value:
    00465
    00466     NTSTATUS - Result code from call, among the following:
    00467
    00468         <TBS>
    00469
    00470 --*/
    00471 {
    00472     NTSTATUS    status;
    00473     PHHIVE Hive;
    00474     PCM_KEY_NODE Node;
    00475     PCELL_DATA ChildList;
    00476     PCM_KEY_VALUE ValueData;
    00477     BOOLEAN    IndexCached;
    00478     BOOLEAN    ValueCached;
    00479     PPCM_CACHED_VALUE ContainingList;
    00480
    00481     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmEnumerateValueKey\n"));
    00482
    00483
    00484     //
    00485     // lock the parent cell
    00486     //
    00487
    00488     CmpLockRegistry();
    00489
    00490     if (KeyControlBlock->Delete) {
    00491         CmpUnlockRegistry();
    00492         return STATUS_KEY_DELETED;
    00493     }
    00494     Hive = KeyControlBlock->KeyHive;
    00495     Node = KeyControlBlock->KeyNode;
    00496
    00497     //
    00498     // fetch the child of interest
    00499     //
    00500     //
    00501     // Do it using the cache
    00502     //
    00503     if (Index >= KeyControlBlock->ValueCache.Count) {
    00504         //
    00505         // No such child, clean up and return error.
    00506         //
    00507         CmpUnlockRegistry();
    00508         return(STATUS_NO_MORE_ENTRIES);
    00509     }
    00510
    00511     // Mark the hive as read only
    00512     CmpMarkAllBinsReadOnly(Hive);
    00513
    00514     LOCK_KCB_TREE();
    00515     if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00516         //
    00517         // The value list is now set to the KCB for symbolic link,
    00518         // Clean it up and set the value right before we do the query.
    00519         //
    00520         CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
    00521         KeyControlBlock->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    00522
    00523         KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
    00524         KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) KeyControlBlock->KeyNode->ValueList.List;
    00525     }
    00526
    00527     ChildList = CmpGetValueListFromCache(Hive, &(KeyControlBlock->ValueCache), &IndexCached);
    00528     ValueData = CmpGetValueKeyFromCache(Hive, ChildList, Index, &ContainingList, IndexCached, &ValueCached);
    00529
    00530     try {
    00531
    00532         // Trying to catch the BAD guy who writes over our pool.
    00533         CmpMakeValueCacheReadWrite(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00534
    00535         //
    00536         // call a worker to perform data transfer
    00537         //
    00538         status = CmpQueryKeyValueData(Hive,
    00539                                   ContainingList,
    00540                                   ValueData,
    00541                                   ValueCached,
    00542                                   KeyValueInformationClass,
    00543                                   KeyValueInformation,
    00544                                   Length,
    00545                                   ResultLength);
    00546
    00547          // Trying to catch the BAD guy who writes over our pool.
    00548         CmpMakeValueCacheReadOnly(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00549     } finally {
    00550
    00551         UNLOCK_KCB_TREE();
    00552         CmpUnlockRegistry();
    00553     }
    00554
    00555     // Mark the hive as read only
    00556     CmpMarkAllBinsReadOnly(Hive);
    00557
    00558     return status;
    00559 }

NTSTATUS CmFlushKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell
| ) |

Definition at line 564 of file cmapi.c.

References CMHIVE, CML_MAJOR, CML_WORKER, CmLockHive, CMLOG, CmpDoFlushAll(), CmpMarkAllBinsReadOnly, CmpMasterHive, CmpNoWrite, CMS_CM, CMS_IO_ERROR, CmUnlockHive, DCmCheckRegistry, Hive, HvSyncHive(), NTSTATUS(), and PCMHIVE.

Referenced by CmpWorker(), and CmpWorkerCommand().

    00570                    :
    00571
    00572     Forces changes made to a key to disk.
    00573
    00574     CmFlushKey will not return to its caller until any changed data
    00575     associated with the key has been written out.
    00576
    00577     WARNING: CmFlushKey will flush the entire registry tree, and thus will
    00578     burn cycles and I/O.
    00579
    00580 Arguments:
    00581
    00582     Hive - supplies a pointer to the hive control structure for the hive
    00583
    00584     Cell - supplies index of node to whose sub keys are to be found
    00585
    00586 Return Value:
    00587
    00588     NTSTATUS - Result code from call, among the following:
    00589
    00590         <TBS>
    00591
    00592 --*/
    00593 {
    00594     PCMHIVE CmHive;
    00595     NTSTATUS    status = STATUS_SUCCESS;
    00596     extern PCMHIVE CmpMasterHive;
    00597
    00598     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmFlushKey\n"));
    00599
    00600     //
    00601     // If writes are not working, lie and say we succeeded, will
    00602     // clean up in a short time.  Only early system init code
    00603     // will ever know the difference.
    00604     //
    00605     if (CmpNoWrite) {
    00606         return STATUS_SUCCESS;
    00607     }
    00608
    00609
    00610     // Mark the hive as read only
    00611     CmpMarkAllBinsReadOnly(Hive);
    00612
    00613     CmHive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    00614
    00615     //
    00616     // Don't flush the master hive.  If somebody asks for a flushkey on
    00617     // the master hive, do a CmpDoFlushAll instead.  CmpDoFlushAll flushes
    00618     // every hive except the master hive, which is what they REALLY want.
    00619     //
    00620     if (CmHive == CmpMasterHive) {
    00621         CmpDoFlushAll();
    00622     } else {
    00623         DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    00624
    00625         CmLockHive (CmHive);
    00626
    00627         if (! HvSyncHive(Hive)) {
    00628
    00629             status = STATUS_REGISTRY_IO_FAILED;
    00630
    00631             CMLOG(CML_MAJOR, CMS_IO_ERROR) {
    00632                 KdPrint(("CmFlushKey: HvSyncHive failed\n"));
    00633             }
    00634         }
    00635
    00636         CmUnlockHive (CmHive);
    00637     }
    00638
    00639     // Mark the hive as read only
    00640     CmpMarkAllBinsReadOnly(Hive);
    00641
    00642     return  status;
    00643 }

NTSTATUS CmLoadKey | ( | IN POBJECT_ATTRIBUTES | TargetKey,
|  | IN POBJECT_ATTRIBUTES | SourceFile,
|  | IN ULONG | Flags
| ) |

Definition at line 1901 of file cmapi.c.

References _REGISTRY_COMMAND::Allocate, ASSERT, _REGISTRY_COMMAND::CmHive, CmpLinkHiveToMaster(), CmpProfileLoaded, CmpSetGlobalQuotaAllowed(), CmpUnlockRegistry(), CmpWasSetupBoot, CmpWorker(), _REGISTRY_COMMAND::Command, FALSE, _REGISTRY_COMMAND::FileAttributes, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, _REGISTRY_COMMAND::ImpersonationContext, KeGetCurrentThread, NT_SUCCESS, NTSTATUS(), REG_CMD_ADD_HIVE_LIST, REG_CMD_HIVE_CLOSE, REG_CMD_HIVE_OPEN, REGISTRY_COMMAND, _REGISTRY_COMMAND::RegistryLockAquired, SeCreateClientSecurity(), SECURITY_CLIENT_CONTEXT, SeDeleteClientSecurity, _REGISTRY_COMMAND::Status, Status, and TRUE.

Referenced by NtLoadKey2().

    01909                    :
    01910
    01911     A hive (file in the format created by NtSaveKey) may be linked
    01912     into the active registry with this call.  UNLIKE NtRestoreKey,
    01913     the file specified to NtLoadKey will become the actual backing
    01914     store of part of the registry (that is, it will NOT be copied.)
    01915
    01916     The file may have an associated .log file.
    01917
    01918     If the hive file is marked as needing a .log file, and one is
    01919     not present, the call will fail.
    01920
    01921     The name specified by SourceFile must be such that ".log" can
    01922     be appended to it to generate the name of the log file.  Thus,
    01923     on FAT file systems, the hive file may not have an extension.
    01924
    01925     This call is used by logon to make the user's profile available
    01926     in the registry.  It is not intended for use doing backup,
    01927     restore, etc.  Use NtRestoreKey for that.
    01928
    01929     N.B.  This routine assumes that the object attributes for the file
    01930           to be opened have been captured into kernel space so that
    01931           they can safely be passed to the worker thread to open the file
    01932           and do the actual I/O.
    01933
    01934 Arguments:
    01935
    01936     TargetKey - specifies the path to a key to link the hive to.
    01937                 path must be of the form "\registry\user<username>"
    01938
    01939     SourceFile - specifies a file.  while file could be remote,
    01940                 that is strongly discouraged.
    01941
    01942     Flags - specifies any flags that should be used for the load operation.
    01943             The only valid flag is REG_NO_LAZY_FLUSH.
    01944
    01945 Return Value:
    01946
    01947     NTSTATUS - values TBS.
    01948
    01949 --*/
    01950 {
    01951     PCMHIVE NewHive;
    01952     NTSTATUS Status;
    01953     BOOLEAN Allocate;
    01954     REGISTRY_COMMAND Command;
    01955     SECURITY_QUALITY_OF_SERVICE ServiceQos;
    01956     SECURITY_CLIENT_CONTEXT ClientSecurityContext;
    01957
    01958
    01959     //
    01960     // Obtain the security context here so we can use it
    01961     // later to impersonate the user, which we will do
    01962     // if we cannot access the file as SYSTEM.  This
    01963     // usually occurs if the file is on a remote machine.
    01964     //
    01965     ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
    01966     ServiceQos.ImpersonationLevel = SecurityImpersonation;
    01967     ServiceQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    01968     ServiceQos.EffectiveOnly = TRUE;
    01969     Status = SeCreateClientSecurity(CONTAINING_RECORD(KeGetCurrentThread(),ETHREAD,Tcb),
    01970                                     &ServiceQos,
    01971                                     FALSE,
    01972                                     &ClientSecurityContext);
    01973     if (!NT_SUCCESS(Status)) {
    01974         return(Status);
    01975     }
    01976
    01977     //
    01978     // Do not lock the registry; Instead set the RegistryLockAquired member
    01979     // of REGISTRY_COMMAND so CmpWorker can lock it after opening the hive files
    01980     //
    01981     //CmpLockRegistryExclusive();
    01982     //
    01983
    01984     Command.RegistryLockAquired = FALSE;
    01985     Command.Command = REG_CMD_HIVE_OPEN;
    01986     Command.Allocate = TRUE;
    01987     Command.FileAttributes = SourceFile;
    01988     Command.ImpersonationContext = &ClientSecurityContext;
    01989
    01990     CmpWorker(&Command);
    01991     Status = Command.Status;
    01992
    01993     SeDeleteClientSecurity( &ClientSecurityContext );
    01994
    01995     NewHive = Command.CmHive;
    01996     Allocate = Command.Allocate;
    01997
    01998     if (!NT_SUCCESS(Status)) {
    01999         if( Command.RegistryLockAquired ) {
    02000             // if CmpWorker has locked the registry, unlock it now.
    02001             CmpUnlockRegistry();
    02002         }
    02003         return(Status);
    02004     } else {
    02005         //
    02006         // if we got here, CmpWorker should have locked the registry exclusive.
    02007         //
    02008         ASSERT( Command.RegistryLockAquired );
    02009     }
    02010
    02011     //
    02012     // if this is a NO_LAZY_FLUSH hive, set the appropriate bit.
    02013     //
    02014     if (Flags & REG_NO_LAZY_FLUSH) {
    02015         NewHive->Hive.HiveFlags |= HIVE_NOLAZYFLUSH;
    02016     }
    02017
    02018     //
    02019     // We now have a succesfully loaded and initialized CmHive, so we
    02020     // just need to link that into the appropriate spot in the master hive.
    02021     //
    02022     Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
    02023                                  TargetKey->RootDirectory,
    02024                                  NewHive,
    02025                                  Allocate,
    02026                                  TargetKey->SecurityDescriptor);
    02027
    02028     Command.CmHive = NewHive;
    02029     if (NT_SUCCESS(Status)) {
    02030         //
    02031         // add new hive to hivelist
    02032         //
    02033         Command.Command = REG_CMD_ADD_HIVE_LIST;
    02034
    02035     } else {
    02036         //
    02037         // Close the files we've opened.
    02038         //
    02039         Command.Command = REG_CMD_HIVE_CLOSE;
    02040     }
    02041     CmpWorker(&Command);
    02042
    02043     //
    02044     // We've given user chance to log on, so turn on quota
    02045     //
    02046     if ((CmpProfileLoaded == FALSE) &&
    02047         (CmpWasSetupBoot == FALSE)) {
    02048         CmpProfileLoaded = TRUE;
    02049         CmpSetGlobalQuotaAllowed();
    02050     }
    02051
    02052     CmpUnlockRegistry();
    02053     return(Status);
    02054 }

NTSTATUS CmpAddAcpiAliasEntry | ( | IN HANDLE | IDConfigDB,
|  | IN PPROFILE_ACPI_DOCKING_STATE | NewDockState,
|  | IN ULONG | ProfileNumber,
|  | IN PWCHAR | nameBuffer,
|  | IN PVOID | valueBuffer,
|  | IN ULONG | valueBufferLength,
|  | IN BOOLEAN | PreventDuplication
| ) |

Definition at line 544 of file hwprofil.c.

References CM_HARDWARE_PROFILE_STR_ACPI_ALIAS, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER, CM_HARDWARE_PROFILE_STR_DOCKING_STATE, CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER, CML_BUGCHECK, CMLOG, CMS_INIT, L, NT_SUCCESS, NtClose(), NtCreateKey(), NtOpenKey(), NtQueryValueKey(), NtSetValueKey(), NTSTATUS(), NULL, PAGED_CODE, and RtlInitUnicodeString().

Referenced by CmpCreateControlSet(), and CmSetAcpiHwProfile().

    00554                    :
    00555     Set the Acpi Alais entry.
    00556
    00557
    00558     Routine Description:
    00559     Create an alias entry in the IDConfigDB database for the given
    00560     hardware profile.
    00561
    00562     Create the "AcpiAlias" key if it does not exist.
    00563
    00564 Parameters:
    00565
    00566     IDConfigDB - Pointer to "..\CurrentControlSet\Control\IDConfigDB"
    00567
    00568     NewDockState - The new docking state for which this alias points.
    00569
    00570     ProfileNumber -The profile number to which this alias points.
    00571
    00572     nameBuffer - a temp scratch space for writing things.
    00573                 (assumed to be at least 128 WCHARS)
    00574
    00575 --*/
    00576 {
    00577     OBJECT_ATTRIBUTES attributes;
    00578     NTSTATUS        status = STATUS_SUCCESS;
    00579     ANSI_STRING     ansiString;
    00580     UNICODE_STRING  name;
    00581     HANDLE          aliasKey = NULL;
    00582     HANDLE          aliasEntry = NULL;
    00583     ULONG           value;
    00584     ULONG           disposition;
    00585     ULONG           aliasNumber = 0;
    00586     ULONG           len;
    00587     PKEY_VALUE_FULL_INFORMATION   keyInfo;
    00588
    00589     PAGED_CODE ();
    00590
    00591     keyInfo = (PKEY_VALUE_FULL_INFORMATION) valueBuffer;
    00592
    00593     //
    00594     // Find the Alias Key or Create it if it does not already exist.
    00595     //
    00596     RtlInitUnicodeString (&name,CM_HARDWARE_PROFILE_STR_ACPI_ALIAS);
    00597
    00598     InitializeObjectAttributes (&attributes,
    00599                                 &name,
    00600                                 OBJ_CASE_INSENSITIVE,
    00601                                 IDConfigDB,
    00602                                 NULL);
    00603
    00604     status = NtOpenKey (&aliasKey,
    00605                         KEY_READ | KEY_WRITE,
    00606                         &attributes);
    00607
    00608     if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
    00609         status = NtCreateKey (&aliasKey,
    00610                               KEY_READ | KEY_WRITE,
    00611                               &attributes,
    00612                               0, // no title
    00613                               NULL, // no class
    00614                               0, // no options
    00615                               &disposition);
    00616     }
    00617
    00618     if (!NT_SUCCESS (status)) {
    00619         aliasKey = NULL;
    00620         goto Exit;
    00621     }
    00622
    00623     //
    00624     // Create an entry key
    00625     //
    00626
    00627     while (aliasNumber < 200) {
    00628         aliasNumber++;
    00629
    00630         swprintf (nameBuffer, L"%04d", aliasNumber);
    00631         RtlInitUnicodeString (&name, nameBuffer);
    00632
    00633         InitializeObjectAttributes(&attributes,
    00634                                    &name,
    00635                                    OBJ_CASE_INSENSITIVE,
    00636                                    aliasKey,
    00637                                    NULL);
    00638
    00639         status = NtOpenKey (&aliasEntry,
    00640                             KEY_READ | KEY_WRITE,
    00641                             &attributes);
    00642
    00643         if (NT_SUCCESS (status)) {
    00644
    00645             if (PreventDuplication) {
    00646                 //
    00647                 // If we have a matching DockingState, SerialNumber, and
    00648                 // Profile Number, then we should not make this alias
    00649                 //
    00650
    00651                 //
    00652                 // Extract The DockingState to which this alias refers.
    00653                 //
    00654                 RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_DOCKING_STATE);
    00655                 status = NtQueryValueKey(aliasEntry,
    00656                                          &name,
    00657                                          KeyValueFullInformation,
    00658                                          valueBuffer,
    00659                                          valueBufferLength,
    00660                                          &len);
    00661
    00662                 if (!NT_SUCCESS (status) || (keyInfo->Type != REG_DWORD)) {
    00663                     status = STATUS_REGISTRY_CORRUPT;
    00664                     goto Exit;
    00665                 }
    00666
    00667                 if (NewDockState->DockingState !=
    00668                     * (PULONG) ((PUCHAR) keyInfo + keyInfo->DataOffset)) {
    00669                     //
    00670                     // Not a dupe
    00671                     //
    00672
    00673                     NtClose (aliasEntry);
    00674                     aliasEntry = NULL;
    00675                     continue;
    00676                 }
    00677
    00678                 //
    00679                 // Extract the SerialNumber
    00680                 //
    00681                 RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER);
    00682                 status = NtQueryValueKey(aliasEntry,
    00683                                          &name,
    00684                                          KeyValueFullInformation,
    00685                                          valueBuffer,
    00686                                          valueBufferLength,
    00687                                          &len);
    00688
    00689                 if (!NT_SUCCESS (status) || (keyInfo->Type != REG_BINARY)) {
    00690                     status = STATUS_REGISTRY_CORRUPT;
    00691                     goto Exit;
    00692                 }
    00693
    00694                 if (NewDockState->SerialLength != keyInfo->DataLength) {
    00695                     //
    00696                     // Not a dupe
    00697                     //
    00698
    00699                     NtClose (aliasEntry);
    00700                     aliasEntry = NULL;
    00701                     continue;
    00702                 }
    00703
    00704                 if (!RtlEqualMemory (NewDockState->SerialNumber,
    00705                                      ((PUCHAR) keyInfo + keyInfo->DataOffset),
    00706                                      NewDockState->SerialLength)) {
    00707                     //
    00708                     // Not a dupe
    00709                     //
    00710
    00711                     NtClose (aliasEntry);
    00712                     aliasEntry = NULL;
    00713                     continue;
    00714                 }
    00715
    00716                 status = STATUS_SUCCESS;
    00717                 goto Exit;
    00718
    00719             }
    00720
    00721         } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
    00722             status = STATUS_SUCCESS;
    00723             break;
    00724
    00725         } else {
    00726             break;
    00727         }
    00728
    00729     }
    00730     if (!NT_SUCCESS (status)) {
    00731         CMLOG(CML_BUGCHECK, CMS_INIT) {
    00732             KdPrint(("CM: cmpCreateAcpiAliasEntry error finding new set %08lx\n",
    00733                      status));
    00734         }
    00735         aliasEntry = 0;
    00736         goto Exit;
    00737     }
    00738
    00739     status = NtCreateKey (&aliasEntry,
    00740                           KEY_READ | KEY_WRITE,
    00741                           &attributes,
    00742                           0,
    00743                           NULL,
    00744                           0,
    00745                           &disposition);
    00746
    00747     if (!NT_SUCCESS (status)) {
    00748         CMLOG(CML_BUGCHECK, CMS_INIT) {
    00749             KdPrint(("CM: cmpCreateAcpiAliasEntry error creating new set %08lx\n",
    00750                      status));
    00751         }
    00752         aliasEntry = 0;
    00753         goto Exit;
    00754     }
    00755
    00756     //
    00757     // Write the Docking State;
    00758     //
    00759     value = NewDockState->DockingState;
    00760     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_DOCKING_STATE);
    00761     status = NtSetValueKey (aliasEntry,
    00762                             &name,
    00763                             0,
    00764                             REG_DWORD,
    00765                             &value,
    00766                             sizeof (value));
    00767
    00768     //
    00769     // Write the Serial Number
    00770     //
    00771     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER);
    00772     status = NtSetValueKey (aliasEntry,
    00773                             &name,
    00774                             0,
    00775                             REG_BINARY,
    00776                             NewDockState->SerialNumber,
    00777                             NewDockState->SerialLength);
    00778
    00779     //
    00780     // Write the Profile Number
    00781     //
    00782     value = ProfileNumber;
    00783     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER);
    00784     status = NtSetValueKey (aliasEntry,
    00785                             &name,
    00786                             0,
    00787                             REG_DWORD,
    00788                             &value,
    00789                             sizeof (value));
    00790
    00791 Exit:
    00792
    00793     if (aliasKey) {
    00794         NtClose (aliasKey);
    00795     }
    00796
    00797     if (aliasEntry) {
    00798         NtClose (aliasEntry);
    00799     }
    00800
    00801     return status;
    00802 }

BOOLEAN CmpAddSubKey | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Parent,
|  | HCELL_INDEX | Child
| ) |

Definition at line 895 of file cmindex.c.

References _HHIVE::Allocate, _CM_INDEX::Cell, CM_KEY_FAST_LEAF, CM_KEY_INDEX_LEAF, CM_KEY_INDEX_ROOT, CM_MAX_FAST_INDEX, CM_MAX_INDEX, CML_MAJOR, CMLOG, CmpAddToLeaf(), CmpCompressedNameSize(), CmpCopyCompressedName(), CmpSelectLeaf(), CMS_INDEX, ErrorExit(), FALSE, _CM_KEY_NODE::Flags, _HHIVE::Free, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, Index, KEY_COMP_NAME, _CM_KEY_FAST_INDEX::List, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NewName, NULL, PHCELL_INDEX, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, and UseFastIndex.

Referenced by CmpCopySyncTree2(), CmpCreateLinkNode(), CmpDoCreate(), and EhCreateChild().

    00902                    :
    00903
    00904     Add a new child subkey to the subkey index for a cell.  The
    00905     child MUST NOT already be present (bugcheck if so.)
    00906
    00907     NOTE:   We expect Parent to already be marked dirty.
    00908             We will mark stuff in Index dirty
    00909
    00910 Arguments:
    00911
    00912     Hive - pointer to hive control structure for hive of interest
    00913
    00914     Parent - cell of key that will be parent of new key
    00915
    00916     Child - new key to put in Paren't sub key list
    00917
    00918 Return Value:
    00919
    00920     TRUE - it worked
    00921
    00922     FALSE - resource problem
    00923
    00924 --*/
    00925 {
    00926     PCM_KEY_NODE    pcell;
    00927     HCELL_INDEX     WorkCell;
    00928     PCM_KEY_INDEX   Index;
    00929     PCM_KEY_FAST_INDEX FastIndex;
    00930     UNICODE_STRING  NewName;
    00931     HCELL_INDEX     LeafCell;
    00932     PHCELL_INDEX    RootPointer = NULL;
    00933     ULONG           cleanup = 0;
    00934     ULONG           Type;
    00935     BOOLEAN         IsCompressed;
    00936     ULONG           i;
    00937
    00938     CMLOG(CML_MAJOR, CMS_INDEX) {
    00939         KdPrint(("CmpAddSubKey:\n\t"));
    00940         KdPrint(("Hive=%08lx Parent=%08lx Child=%08lx\n",Hive,Parent,Child));
    00941     }
    00942
    00943     //
    00944     // build a name string
    00945     //
    00946     pcell = (PCM_KEY_NODE)HvGetCell(Hive, Child);
    00947     if (pcell->Flags & KEY_COMP_NAME) {
    00948         IsCompressed = TRUE;
    00949         NewName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
    00950         NewName.MaximumLength = NewName.Length;
    00951         NewName.Buffer = (Hive->Allocate)(NewName.Length, FALSE);
    00952         if (NewName.Buffer==NULL) {
    00953             return(FALSE);
    00954         }
    00955         CmpCopyCompressedName(NewName.Buffer,
    00956                               NewName.MaximumLength,
    00957                               pcell->Name,
    00958                               pcell->NameLength);
    00959     } else {
    00960         IsCompressed = FALSE;
    00961         NewName.Length = pcell->NameLength;
    00962         NewName.MaximumLength = pcell->NameLength;
    00963         NewName.Buffer = &(pcell->Name[0]);
    00964     }
    00965
    00966     pcell = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
    00967
    00968     Type = HvGetCellType(Child);
    00969
    00970     if (pcell->SubKeyCounts[Type] == 0) {
    00971
    00972         ULONG Signature;
    00973
    00974         //
    00975         // we must allocate a leaf
    00976         //
    00977         WorkCell = HvAllocateCell(Hive, sizeof(CM_KEY_FAST_INDEX), Type);
    00978         if (WorkCell == HCELL_NIL) {
    00979             goto ErrorExit;
    00980         }
    00981         Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
    00982         Index->Signature = UseFastIndex(Hive) ? CM_KEY_FAST_LEAF : CM_KEY_INDEX_LEAF;
    00983         Index->Count = 0;
    00984         pcell->SubKeyLists[Type] = WorkCell;
    00985         cleanup = 1;
    00986     } else {
    00987
    00988         Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
    00989         if ((Index->Signature == CM_KEY_FAST_LEAF) &&
    00990             (Index->Count >= (CM_MAX_FAST_INDEX))) {
    00991
    00992             //
    00993             // We must change fast index to a slow index to accomodate
    00994             // growth.
    00995             //
    00996
    00997             FastIndex = (PCM_KEY_FAST_INDEX)Index;
    00998             for (i=0; i<Index->Count; i++) {
    00999                 Index->List[i] = FastIndex->List[i].Cell;
    01000             }
    01001             Index->Signature = CM_KEY_INDEX_LEAF;
    01002
    01003         } else if ((Index->Signature == CM_KEY_INDEX_LEAF) &&
    01004                    (Index->Count >= (CM_MAX_INDEX - 1) )) {
    01005             //
    01006             // We must change flat entry to a root/leaf tree
    01007             //
    01008             WorkCell = HvAllocateCell(
    01009                          Hive,
    01010                          sizeof(CM_KEY_INDEX) + sizeof(HCELL_INDEX), // allow for 2
    01011                          Type
    01012                          );
    01013             if (WorkCell == HCELL_NIL) {
    01014                 goto ErrorExit;
    01015             }
    01016
    01017             Index = (PCM_KEY_INDEX)HvGetCell(Hive, WorkCell);
    01018             Index->Signature = CM_KEY_INDEX_ROOT;
    01019             Index->Count = 1;
    01020             Index->List[0] = pcell->SubKeyLists[Type];
    01021             pcell->SubKeyLists[Type] = WorkCell;
    01022             cleanup = 2;
    01023
    01024         }
    01025     }
    01026     LeafCell = pcell->SubKeyLists[Type];
    01027
    01028     //
    01029     // LeafCell is target for add, or perhaps root
    01030     // Index is pointer to fast leaf, slow Leaf or Root, whichever applies
    01031     //
    01032     if (Index->Signature == CM_KEY_INDEX_ROOT) {
    01033         LeafCell = CmpSelectLeaf(Hive, pcell, &NewName, Type, &RootPointer);
    01034         if (LeafCell == HCELL_NIL) {
    01035             goto ErrorExit;
    01036         }
    01037     }
    01038
    01039     //
    01040     // Add new cell to Leaf, update pointers
    01041     //
    01042     LeafCell = CmpAddToLeaf(Hive, LeafCell, Child, &NewName);
    01043
    01044     if (LeafCell == HCELL_NIL) {
    01045         goto ErrorExit;
    01046     }
    01047
    01048     pcell->SubKeyCounts[Type] += 1;
    01049
    01050     if (RootPointer != NULL) {
    01051         *RootPointer = LeafCell;
    01052     } else {
    01053         pcell->SubKeyLists[Type] = LeafCell;
    01054     }
    01055
    01056     if (IsCompressed) {
    01057         (Hive->Free)(NewName.Buffer, NewName.Length);
    01058     }
    01059
    01060     return TRUE;
    01061
    01062
    01063
    01064 ErrorExit:
    01065     if (IsCompressed) {
    01066         (Hive->Free)(NewName.Buffer, NewName.Length);
    01067     }
    01068
    01069     switch (cleanup) {
    01070     case 1:
    01071         HvFreeCell(Hive, pcell->SubKeyLists[Type]);
    01072         pcell->SubKeyLists[Type] = HCELL_NIL;
    01073         break;
    01074
    01075     case 2:
    01076         Index = (PCM_KEY_INDEX)HvGetCell(Hive, pcell->SubKeyLists[Type]);
    01077         pcell->SubKeyLists[Type] = Index->List[0];
    01078         HvFreeCell(Hive, pcell->SubKeyLists[Type]);
    01079         break;
    01080     }
    01081
    01082     return  FALSE;
    01083 }

NTSTATUS CmpAddToHiveFileList | ( | PCMHIVE | CmHive | ) |

Definition at line 42 of file cmhvlist.c.

References Buffer, CML_MAJOR, CMLOG, CmpGetHiveName(), CMS_INIT_ERROR, ExAllocatePool, ExFreePool(), _CMHIVE::FileHandles, HFILE_TYPE_PRIMARY, _CMHIVE::Hive, HIVE_LIST, HIVE_VOLATILE, _HHIVE::HiveFlags, NAME_BUFFER_SIZE, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObjectAttributes, PagedPool, RtlInitUnicodeString(), Status, and UnicodeNull.

Referenced by CmInitSystem1(), CmpInitializeHiveList(), and CmpWorker().

    00047                    :
    00048
    00049     Add Hive to list of hives and their files in
    00050     \registry\machine\system\currentcontrolset\control\hivelist
    00051
    00052 Arguments:
    00053
    00054     HivePath - path to root of hive (e.g. \registry\machine\system)
    00055
    00056     CmHive - pointer to CM_HIVE structure for hive.
    00057
    00058 Return Value:
    00059
    00060     ntstatus
    00061
    00062 --*/
    00063 {
    00064 //
    00065 //  PERFNOTE - allocate small instead of large buffers after
    00066 //           NtQueryObject is fixec - bryanwi 15may92
    00067 //
    00068 #define NAME_BUFFER_SIZE    512
    00069     OBJECT_ATTRIBUTES   ObjectAttributes;
    00070     HANDLE              KeyHandle;
    00071     NTSTATUS            Status;
    00072     PUCHAR              Buffer;
    00073     ULONG               Length;
    00074     PWSTR               FilePath;
    00075     WCHAR               UnicodeNull=UNICODE_NULL;
    00076     UNICODE_STRING      TempName;
    00077     UNICODE_STRING      HivePath;
    00078
    00079     //
    00080     // create/open the hive list key
    00081     //
    00082     RtlInitUnicodeString(
    00083         &TempName,
    00084         HIVE_LIST
    00085         );
    00086
    00087     InitializeObjectAttributes(
    00088         &ObjectAttributes,
    00089         &TempName,
    00090         OBJ_CASE_INSENSITIVE,
    00091         (HANDLE)NULL,
    00092         NULL
    00093         );
    00094
    00095     Status = ZwCreateKey(
    00096                 &KeyHandle,
    00097                 KEY_READ | KEY_WRITE,
    00098                 &ObjectAttributes,
    00099                 0,
    00100                 NULL,
    00101                 REG_OPTION_VOLATILE,
    00102                 NULL
    00103                 );
    00104
    00105     if (!NT_SUCCESS(Status)) {
    00106         CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    00107             KdPrint(("CmpAddToHiveFileList: "));
    00108             KdPrint(("Create/Open of Hive list failed status = %08lx\n", Status));
    00109         }
    00110         return Status;
    00111     }
    00112
    00113     //
    00114     // allocate work buffers
    00115     //
    00116     Buffer = ExAllocatePool(PagedPool, NAME_BUFFER_SIZE);
    00117     if (Buffer == NULL) {
    00118         NtClose(KeyHandle);
    00119         return STATUS_NO_MEMORY;
    00120     }
    00121
    00122     //
    00123     // compute name of hive
    00124     //
    00125     if (! CmpGetHiveName(CmHive, &HivePath)) {
    00126         NtClose(KeyHandle);
    00127         ExFreePool(Buffer);
    00128         return STATUS_NO_MEMORY;
    00129     }
    00130
    00131
    00132     //
    00133     // get name of file
    00134     //
    00135     if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) {
    00136         Status = ZwQueryObject(
    00137                     CmHive->FileHandles[HFILE_TYPE_PRIMARY],
    00138                     ObjectNameInformation,
    00139                     (PVOID)Buffer,
    00140                     NAME_BUFFER_SIZE,
    00141                     &Length
    00142                     );
    00143         Length -= sizeof(UNICODE_STRING);
    00144         if (!NT_SUCCESS(Status)) {
    00145             CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    00146                 KdPrint(("CmpAddToHiveFileList: "));
    00147                 KdPrint(("Query of name2 failed status = %08lx\n", Status));
    00148             }
    00149             NtClose(KeyHandle);
    00150             ExFreePool(HivePath.Buffer);
    00151             ExFreePool(Buffer);
    00152             return  Status;
    00153         }
    00154         FilePath = ((POBJECT_NAME_INFORMATION)Buffer)->Name.Buffer;
    00155         FilePath[Length/sizeof(WCHAR)] = UNICODE_NULL;
    00156         Length+=sizeof(WCHAR);
    00157     } else {
    00158         FilePath = &UnicodeNull;
    00159         Length = sizeof(UnicodeNull);
    00160     }
    00161
    00162     //
    00163     // set entry in list
    00164     //
    00165     Status = ZwSetValueKey(
    00166                 KeyHandle,
    00167                 &HivePath,
    00168                 0,
    00169                 REG_SZ,
    00170                 FilePath,
    00171                 Length
    00172                 );
    00173     if (!NT_SUCCESS(Status)) {
    00174         CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    00175             KdPrint(("CmpAddToHiveFileList: "));
    00176             KdPrint(("Set of entry in Hive list failed status = %08lx\n", Status));
    00177         }
    00178     }
    00179
    00180     NtClose(KeyHandle);
    00181     ExFreePool(HivePath.Buffer);
    00182     ExFreePool(Buffer);
    00183     return  Status;
    00184 }

PVOID CmpAllocate | ( | ULONG | Size,
|  | BOOLEAN | UseForIo
| ) |

Definition at line 62 of file cmwrapr.c.

References CML_MINOR, CMLOG, CmpClaimGlobalQuota(), CmpReleaseGlobalQuota(), CMS_POOL, ExAllocatePoolWithTag, FALSE, NULL, PagedPool, PagedPoolCacheAligned, RtlGetCallersAddress(), and Size.

Referenced by CmpInitializeHive().

    00068                    :
    00069
    00070     This routine makes more memory available to a hive.
    00071
    00072     It is environment specific.
    00073
    00074 Arguments:
    00075
    00076     Size - amount of space caller wants
    00077
    00078     UseForIo - TRUE if object allocated will be target of I/O,
    00079                FALSE if not.
    00080
    00081 Return Value:
    00082
    00083     NULL if failure, address of allocated block if not.
    00084
    00085 --*/
    00086 {
    00087     PVOID   result;
    00088     ULONG   pooltype;
    00089 #if DBG
    00090     PVOID   Caller;
    00091     PVOID   CallerCaller;
    00092     RtlGetCallersAddress(&Caller, &CallerCaller);
    00093 #endif
    00094
    00095     if (CmpClaimGlobalQuota(Size) == FALSE) {
    00096         return NULL;
    00097     }
    00098
    00099     pooltype = (UseForIo) ? PagedPoolCacheAligned : PagedPool;
    00100     result = ExAllocatePoolWithTag(
    00101                 pooltype,
    00102                 Size,
    00103                 CM_POOL_TAG
    00104                 );
    00105
    00106 #if DBG
    00107     CMLOG(CML_MINOR, CMS_POOL) {
    00108         KdPrint(("**CmpAllocate: allocate:%08lx, ", Size));
    00109         KdPrint(("type:%d, at:%08lx  ", PagedPool, result));
    00110         KdPrint(("c:%08lx  cc:%08lx\n", Caller, CallerCaller));
    00111     }
    00112 #endif
    00113
    00114     if (result == NULL) {
    00115         CmpReleaseGlobalQuota(Size);
    00116     }
    00117
    00118     return result;
    00119 }

PCM_POST_BLOCK CmpAllocatePostBlock | ( | IN POST_BLOCK_TYPE | BlockType,
|  | IN ULONG | PostFlags,
|  | IN PCM_KEY_BODY | KeyBody,
|  | IN PCM_POST_BLOCK | MasterBlock
| ) |

Definition at line 3883 of file ntapi.c.

References ALLOCATE_WITH_QUOTA, ASSERT, CM_POST_BLOCK, CM_POST_BLOCK_UNION, CM_POST_KEY_BODY, ExFreePool(), FALSE, IsMasterPostBlock, KeInitializeEvent, NonPagedPool, NULL, PagedPool, PostAsyncKernel, PostAsyncUser, and PostSynchronous.

    03892                    :
    03893
    03894     Allocates a post block from pool.  The non-pagable stuff comes from
    03895     NonPagedPool, the pagable stuff from paged pool.  Quota will be
    03896     charged.
    03897
    03898 Arguments:
    03899
    03900     BlockType  - specifies the type of the post block to be allocated
    03901                 i.e. : PostSyncrhronous, PostAsyncUser, PostAsyncKernel
    03902
    03903     PostFlags      - specifies the flags to be set on the allocated post block
    03904                 vallid flags:
    03905                     - REG_NOTIFY_MASTER_POST - the post block to be allocated
    03906                       is a master post block.
    03907     KeyBody     - The Key object to whom this post block is attached. On master blocks
    03908                   this is NULL. When the post object is freed, the KeyBody object is
    03909                   dereferenced (if not NULL - i.e. for slave blocks). This allow us to
    03910                   perform back-end cleanup for "fake-slave" keys opened by NtNotifyMultipleKeys
    03911     MasterBlock - the post block to be allocated is a slave of this master block.
    03912                   valid only when PostFlags ==  REG_NOTIFY_MASTER_POST
    03913
    03914
    03915 Obs: The Sync.SystemEvent and AsyncUser.Apc members are allocated only for master post blocks
    03916
    03917 Return Value:
    03918
    03919     Pointer to the CM_POST_BLOCK if successful
    03920
    03921     NULL if there were not enough resources available.
    03922
    03923 --*/
    03924
    03925 {
    03926     PCM_POST_BLOCK PostBlock;
    03927
    03928     // protection against outrageous calls
    03929     ASSERT( !PostFlags || (!MasterBlock && !KeyBody) );
    03930
    03931     PostBlock = ALLOCATE_WITH_QUOTA(PagedPool, sizeof(CM_POST_BLOCK),CM_POSTBLOCK_TAG);
    03932     if (PostBlock==NULL) {
    03933         return(NULL);
    03934     }
    03935
    03936 #ifdef _CM_ENTRYLIST_MANIPULATION
    03937     RtlZeroMemory((PVOID)PostBlock, sizeof(CM_POST_BLOCK));
    03938 #endif
    03939
    03940 #if DBG
    03941     PostBlock->TraceIntoDebugger = FALSE;
    03942 #endif
    03943
    03944     PostBlock->NotifyType = (ULONG)BlockType;
    03945     PostBlock->NotifyType |= PostFlags;
    03946
    03947     if(IsMasterPostBlock(PostBlock)) {
    03948         PostBlock->PostKeyBody = NULL;
    03949         //
    03950         // master post block ==> allocate the storage
    03951         //
    03952         PostBlock->u = ALLOCATE_WITH_QUOTA(NonPagedPool,
    03953                                            sizeof(CM_POST_BLOCK_UNION),
    03954                                            CM_POSTBLOCK_TAG);
    03955         if (PostBlock->u == NULL) {
    03956             ExFreePool(PostBlock);
    03957             return(NULL);
    03958         }
    03959
    03960          switch (BlockType) {
    03961             case PostSynchronous:
    03962                 PostBlock->u->Sync.SystemEvent = ALLOCATE_WITH_QUOTA(NonPagedPool,
    03963                                                                     sizeof(KEVENT),
    03964                                                                     CM_POSTEVENT_TAG);
    03965                 if (PostBlock->u->Sync.SystemEvent == NULL) {
    03966                     ExFreePool(PostBlock->u);
    03967                     ExFreePool(PostBlock);
    03968                     return(NULL);
    03969                 }
    03970                 KeInitializeEvent(PostBlock->u->Sync.SystemEvent,
    03971                                   SynchronizationEvent,
    03972                                   FALSE);
    03973                 break;
    03974             case PostAsyncUser:
    03975                 PostBlock->u->AsyncUser.Apc = ALLOCATE_WITH_QUOTA(NonPagedPool,
    03976                                                              sizeof(KAPC),
    03977                                                              CM_POSTAPC_TAG);
    03978                 if (PostBlock->u->AsyncUser.Apc==NULL) {
    03979                     ExFreePool(PostBlock->u);
    03980                     ExFreePool(PostBlock);
    03981                     return(NULL);
    03982                 }
    03983                 break;
    03984             case PostAsyncKernel:
    03985                 RtlZeroMemory(&PostBlock->u->AsyncKernel, sizeof(CM_ASYNC_KERNEL_POST_BLOCK));
    03986                 break;
    03987         }
    03988     } else {
    03989         //
    03990         // Slave post block ==> copy storage allocated for the master post block
    03991         //
    03992         PostBlock->u = MasterBlock->u;
    03993
    03994         //
    03995         // allocate a PostKeyBody which will hold this KeyBody, and initialize the head of its KeyBodyList
    03996         //
    03997         PostBlock->PostKeyBody = ALLOCATE_WITH_QUOTA(PagedPool, sizeof(CM_POST_KEY_BODY),CM_POSTBLOCK_TAG);
    03998         if (PostBlock->PostKeyBody == NULL) {
    03999             ExFreePool(PostBlock);
    04000             return(NULL);
    04001         }
    04002         PostBlock->PostKeyBody->KeyBody = KeyBody;
    04003         InitializeListHead(&(PostBlock->PostKeyBody->KeyBodyList));
    04004     }
    04005
    04006     return(PostBlock);
    04007 }

NTSTATUS CmpAssignSecurityDescriptor | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PCM_KEY_NODE | Node,
|  | IN PSECURITY_DESCRIPTOR | SecurityDescriptor
| ) |

Definition at line 697 of file cmse.c.

References ASSERT, ASSERT_NODE, Cell, CM_KEY_SECURITY_SIGNATURE, CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpFindMatchingDescriptorCell(), CmpInsertSecurityCellList(), CMS_SEC, _CM_KEY_SECURITY::Descriptor, _CM_KEY_SECURITY::DescriptorLength, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, HvMarkCellDirty(), Name, PAGED_CODE, _CM_KEY_SECURITY::ReferenceCount, RtlLengthSecurityDescriptor(), SECURITY_CELL_LENGTH, and _CM_KEY_SECURITY::Signature.

Referenced by CmpCopyKeyPartial(), CmpSecurityMethod(), and CmpSyncKeyValues().

    00706                    :
    00707
    00708     This routine assigns the given security descriptor to the specified
    00709     node in the configuration tree.
    00710
    00711 Arguments:
    00712
    00713     Hive - Supplies a pointer to the Hive for the node whose security
    00714            descriptor will be assigned.
    00715
    00716     Cell - Supplies the HCELL_INDEX of the node whose security descriptor
    00717            will be assigned.
    00718
    00719     Node - Supplies a pointer to the node whose security descriptor will
    00720            be assigned.
    00721
    00722     SecurityDescriptor - Supplies a pointer to the security descriptor to
    00723            be assigned to the node.
    00724
    00725     PoolType - Supplies the type of pool the SecurityDescriptor was a
    00726            allocated from.
    00727
    00728 Return Value:
    00729
    00730     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error value
    00731         otherwise
    00732
    00733 --*/
    00734
    00735 {
    00736     HCELL_INDEX SecurityCell;
    00737     PCM_KEY_SECURITY Security;
    00738     ULONG DescriptorLength;
    00739     ULONG Type;
    00740
    00741     PAGED_CODE();
    00742     //
    00743     // Map the node that we need to assign the security descriptor to.
    00744     //
    00745     if (! HvMarkCellDirty(Hive, Cell)) {
    00746         return STATUS_NO_LOG_SPACE;
    00747     }
    00748     ASSERT_NODE(Node);
    00749
    00750     CMLOG(CML_FLOW, CMS_SEC) {
    00751 #if DBG
    00752         UNICODE_STRING Name;
    00753
    00754         Name.MaximumLength = Name.Length = Node->NameLength;
    00755         Name.Buffer = Node->Name;
    00756         KdPrint(("CmpAssignSecurityDescriptor: '%wZ' (H %lx C %lx)\n",&Name,Hive,Cell ));
    00757         KdPrint(("\tSecurityCell = %lx\n",Node->Security));
    00758 #endif
    00759     }
    00760
    00761     ASSERT(Node->Security==HCELL_NIL);
    00762
    00763     //
    00764     // This is a CreateKey, so the registry node has just been created and
    00765     // the security descriptor we have been passed needs to be associated
    00766     // with the new registry node and inserted into the hive.
    00767     //
    00768     CMLOG(CML_FLOW, CMS_SEC) {
    00769         CmpDumpSecurityDescriptor(SecurityDescriptor, "ASSIGN DESCRIPTOR\n");
    00770     }
    00771
    00772     //
    00773     // Try to find an existing security descriptor that matches this one.
    00774     // If successful, then we don't need to allocate a new cell, we can
    00775     // just point to the existing one and increment its reference count.
    00776     //
    00777     Type = HvGetCellType(Cell);
    00778     if (!CmpFindMatchingDescriptorCell( Hive,
    00779                                         Node,
    00780                                         SecurityDescriptor,
    00781                                         Type,
    00782                                         &SecurityCell )) {
    00783         //
    00784         // No matching descriptor found, allocate and initialize a new one.
    00785         //
    00786         SecurityCell = HvAllocateCell(Hive,
    00787                                       SECURITY_CELL_LENGTH(SecurityDescriptor),
    00788                                       Type);
    00789         if (SecurityCell == HCELL_NIL) {
    00790             return STATUS_INSUFFICIENT_RESOURCES;
    00791         }
    00792
    00793         //
    00794         // Map the security cell
    00795         //
    00796         Security = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell);
    00797
    00798         //
    00799         // Initialize the security cell
    00800         //
    00801         DescriptorLength = RtlLengthSecurityDescriptor(SecurityDescriptor);
    00802
    00803         Security->Signature = CM_KEY_SECURITY_SIGNATURE;
    00804         Security->ReferenceCount = 1;
    00805         Security->DescriptorLength = DescriptorLength;
    00806         RtlMoveMemory( &(Security->Descriptor),
    00807                        SecurityDescriptor,
    00808                        DescriptorLength );
    00809
    00810         //
    00811         // Insert the new security descriptor into the list of security
    00812         // cells.
    00813         //
    00814         if (!CmpInsertSecurityCellList(Hive,Cell,SecurityCell))
    00815         {
    00816             HvFreeCell(Hive, SecurityCell);
    00817             return STATUS_NO_LOG_SPACE;
    00818         }
    00819
    00820     } else {
    00821
    00822         //
    00823         // Found identical descriptor already existing.  Map it in and
    00824         // increment its reference count.
    00825         //
    00826         if (! HvMarkCellDirty(Hive, SecurityCell)) {
    00827             return STATUS_NO_LOG_SPACE;
    00828         }
    00829         Security = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell);
    00830         Security->ReferenceCount += 1;
    00831     }
    00832
    00833     //
    00834     // Initialize the reference in the node cell
    00835     //
    00836     Node->Security = SecurityCell;
    00837
    00838     CMLOG(CML_FLOW, CMS_SEC) {
    00839         KdPrint(("\tSecurityCell = %lx\n",Node->Security));
    00840     }
    00841
    00842     return(STATUS_SUCCESS);
    00843 }

BOOLEAN CmpCheckCreateAccess | ( | IN PUNICODE_STRING | RelativeName,
|  | IN PSECURITY_DESCRIPTOR | Descriptor,
|  | IN PACCESS_STATE | AccessState,
|  | IN KPROCESSOR_MODE | PreviousMode,
|  | IN ACCESS_MASK | AdditionalAccess,
|  | OUT PNTSTATUS | AccessStatus
| ) |

Definition at line 917 of file cmse.c.

References CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpKeyObjectType, CMS_SEC, FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NULL, PAGED_CODE, SeAccessCheck(), SeCreateObjectAuditAlarm(), SeLockSubjectContext(), SeUnlockSubjectContext(), TRUE, and _OBJECT_TYPE::TypeInfo.

Referenced by CmpDoCreate().

    00928                    :
    00929
    00930     This routine checks to see if we are allowed to create a sub-key in the
    00931     given key, and performs auditing as appropriate.
    00932
    00933 Arguments:
    00934
    00935     RelativeName - Supplies the relative name of the key being created.
    00936
    00937     Descriptor - Supplies the security descriptor of the key in which
    00938         the sub-key is to be created.
    00939
    00940     CreateAccess - The access mask corresponding to create access for
    00941         this directory type.
    00942
    00943     AccessState - Checks for traverse access will typically be incidental
    00944         to some other access attempt.  Information on the current state of
    00945         that access attempt is required so that the constituent access
    00946         attempts may be associated with each other in the audit log.
    00947
    00948     PreviousMode - The previous processor mode.
    00949
    00950     AdditionalAccess - access rights in addition to KEY_CREATE_SUB_KEY
    00951             that are required.  (e.g. KEY_CREATE_LINK)
    00952
    00953     AccessStatus - Pointer to a variable to return the status code of the
    00954         access attempt.  In the case of failure this status code must be
    00955         propagated back to the user.
    00956
    00957 Return Value:
    00958
    00959     BOOLEAN - TRUE if access is allowed and FALSE otherwise.  AccessStatus
    00960     contains the status code to be passed back to the caller.  It is not
    00961     correct to simply pass back STATUS_ACCESS_DENIED, since this will have
    00962     to change with the advent of mandatory access control.
    00963
    00964 --*/
    00965
    00966 {
    00967     BOOLEAN AccessAllowed;
    00968     ACCESS_MASK GrantedAccess = 0;
    00969     BOOLEAN AuditPerformed = FALSE;
    00970
    00971     PAGED_CODE();
    00972     CMLOG(CML_FLOW, CMS_SEC) {
    00973         KdPrint(("CmpCheckCreateAccess:\n"));
    00974     }
    00975
    00976     SeLockSubjectContext( &AccessState->SubjectSecurityContext );
    00977
    00978     AccessAllowed = SeAccessCheck(
    00979                         Descriptor,
    00980                         &AccessState->SubjectSecurityContext,
    00981                         TRUE,                              // Token is read locked
    00982                         (KEY_CREATE_SUB_KEY | AdditionalAccess),
    00983                         0,
    00984                         NULL,
    00985                         &CmpKeyObjectType->TypeInfo.GenericMapping,
    00986                         PreviousMode,
    00987                         &GrantedAccess,
    00988                         AccessStatus
    00989                         );
    00990
    00991     //
    00992     // if the security guys ever get around to implementing this,
    00993     // put this call back in.
    00994     //
    00995 #if 0
    00996     //
    00997     // WARNNOTE John Vert (jvert) 22-Jan-92
    00998     //  We don't have a Directory Object handy, and the auditing currently
    00999     //  ignores it anyway.
    01000     //
    01001
    01002     SeCreateObjectAuditAlarm(
    01003         &AccessState->OperationID,
    01004         NULL,                       // <- see WARNNOTE
    01005         NULL,                       // Need component name
    01006         Descriptor,
    01007         &AccessState->SubjectSecurityContext,
    01008         KEY_CREATE_SUB_KEY,
    01009         AccessState->PrivilegesUsed,
    01010         AccessAllowed,
    01011         &AuditPerformed,
    01012         PreviousMode
    01013         );
    01014 #endif
    01015
    01016     SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
    01017
    01018     CMLOG(CML_FLOW, CMS_SEC) {
    01019         KdPrint(("Create access %s\n",AccessAllowed ? "granted" : "denied"));
    01020 #if DBG
    01021         if (!AccessAllowed) {
    01022             CmpDumpSecurityDescriptor(Descriptor, "DENYING DESCRIPTOR");
    01023         }
    01024 #endif
    01025     }
    01026
    01027     return(AccessAllowed);
    01028 }

ULONG CmpCheckLockExceptionFilter | ( | IN PEXCEPTION_POINTERS | ExceptionPointers | ) |

Definition at line 81 of file ntapi.c.

References EXCEPTION_EXECUTE_HANDLER, and KeBugCheckEx().

    00084 {
    00085     KdPrint(("CM: Registry exception %lx, ExceptionPointers = %lx\n",
    00086             ExceptionPointers->ExceptionRecord->ExceptionCode,
    00087             ExceptionPointers));
    00088
    00089     KeBugCheckEx(REGISTRY_ERROR,12,
    00090         (ULONG_PTR)ExceptionPointers->ExceptionRecord->ExceptionCode,
    00091         (ULONG_PTR)ExceptionPointers->ExceptionRecord,
    00092         (ULONG_PTR)ExceptionPointers->ContextRecord);
    00093
    00094     return EXCEPTION_EXECUTE_HANDLER;
    00095 }

BOOLEAN CmpCheckNotifyAccess | ( | IN PCM_NOTIFY_BLOCK | NotifyBlock,
|  | IN PHHIVE | Hive,
|  | IN PCM_KEY_NODE | Node
| ) |

Definition at line 1032 of file cmse.c.

References ASSERT_CM_LOCK_OWNED, CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpGetKeySecurity(), CmpKeyObjectType, CMS_SEC, _CM_KEY_SECURITY::Descriptor, _OBJECT_TYPE_INITIALIZER::GenericMapping, Hive, NTSTATUS(), NULL, PAGED_CODE, SeAccessCheck(), SeLockSubjectContext(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_TYPE::TypeInfo, and UserMode.

Referenced by CmpNotifyTriggerCheck().

    01039                    :
    01040
    01041     Check whether the subject process/thread/user specified by the
    01042     security data in the NotifyBlock has required access to the
    01043     key specified by Hive.Cell.
    01044
    01045 Arguments:
    01046
    01047     NotifyBlock - pointer to structure that describes the notify
    01048                   operation, including the identity of the subject
    01049                   that opened the notify.
    01050
    01051     Hive - Supplies pointer to hive containing Node.
    01052
    01053     Node - Supplies pointer to key of interest.
    01054
    01055 Return Value:
    01056
    01057     TRUE if RequiredAccess is in fact possessed by the subject,
    01058     else FALSE.
    01059
    01060 --*/
    01061 {
    01062     PCM_KEY_SECURITY Security;
    01063     PSECURITY_DESCRIPTOR SecurityDescriptor;
    01064     NTSTATUS Status;
    01065     BOOLEAN AccessAllowed;
    01066     ACCESS_MASK GrantedAccess = 0;
    01067
    01068     ASSERT_CM_LOCK_OWNED();
    01069     PAGED_CODE();
    01070
    01071
    01072     CMLOG(CML_FLOW, CMS_SEC) {
    01073         KdPrint(("CmpCheckAccessForNotify:\n"));
    01074     }
    01075     Security = CmpGetKeySecurity(Hive,
    01076                                  Node,
    01077                                  NULL);
    01078
    01079     SeLockSubjectContext( &NotifyBlock->SubjectContext );
    01080
    01081     SecurityDescriptor = &Security->Descriptor;
    01082     AccessAllowed = SeAccessCheck( SecurityDescriptor,
    01083                                    &NotifyBlock->SubjectContext,
    01084                                    TRUE,
    01085                                    KEY_NOTIFY,
    01086                                    0,
    01087                                    NULL,
    01088                                    &CmpKeyObjectType->TypeInfo.GenericMapping,
    01089                                    UserMode,
    01090                                    &GrantedAccess,
    01091                                    &Status );
    01092
    01093     SeUnlockSubjectContext( &NotifyBlock->SubjectContext );
    01094
    01095     CMLOG(CML_FLOW, CMS_SEC) {
    01096         KdPrint(("Notify access %s\n",AccessAllowed ? "granted" : "denied"));
    01097 #if DBG
    01098         if (!AccessAllowed) {
    01099             CmpDumpSecurityDescriptor(SecurityDescriptor, "DENYING DESCRIPTOR");
    01100         }
    01101 #endif
    01102     }
    01103
    01104     return AccessAllowed;
    01105 }

BOOLEAN CmpClaimGlobalQuota | ( | IN ULONG | Size | ) |

Definition at line 204 of file cmgquota.c.

References CmpGlobalQuotaAllowed, CmpGlobalQuotaUsed, CmpGlobalQuotaWarning, CmpQuotaWarningPopupDisplayed, CmpQuotaWarningWorker(), DelayedWorkQueue, ExAllocatePool, ExInitializeWorkItem, ExQueueWorkItem(), ExReadyForErrors, FALSE, NonPagedPool, NULL, PWORK_QUEUE_ITEM, Size, and TRUE.

Referenced by CmpAllocate().

    00209                    :
    00210
    00211     If CmpGlobalQuotaUsed + Size >= CmpGlobalQuotaAllowed, return
    00212     false.  Otherwise, increment CmpGlobalQuotaUsed, in effect claiming
    00213     the requested GlobalQuota.
    00214
    00215 Arguments:
    00216
    00217     Size - number of bytes of GlobalQuota caller wants to claim
    00218
    00219 Return Value:
    00220
    00221     TRUE - Claim succeeded, and has been counted in Used GQ
    00222
    00223     FALSE - Claim failed, nothing counted in GQ.
    00224
    00225 --*/
    00226 {
    00227     LONG   available;
    00228     PWORK_QUEUE_ITEM WorkItem;
    00229
    00230     //
    00231     // compute available space, then see if size <.  This prevents overflows.
    00232     // Note that this must be signed. Since quota is not enforced until logon,
    00233     // it is possible for the available bytes to be negative.
    00234     //
    00235
    00236     available = (LONG)CmpGlobalQuotaAllowed - (LONG)CmpGlobalQuotaUsed;
    00237
    00238     if ((LONG)Size < available) {
    00239         CmpGlobalQuotaUsed += Size;
    00240         if ((CmpGlobalQuotaUsed > CmpGlobalQuotaWarning) &&
    00241             (!CmpQuotaWarningPopupDisplayed) &&
    00242             (ExReadyForErrors)) {
    00243
    00244             //
    00245             // Queue work item to display popup
    00246             //
    00247             WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
    00248             if (WorkItem != NULL) {
    00249
    00250                 CmpQuotaWarningPopupDisplayed = TRUE;
    00251                 ExInitializeWorkItem(WorkItem,
    00252                                      CmpQuotaWarningWorker,
    00253                                      WorkItem);
    00254                 ExQueueWorkItem(WorkItem, DelayedWorkQueue);
    00255             }
    00256         }
    00257         return TRUE;
    00258     } else {
    00259         return FALSE;
    00260     }
    00261 }

VOID CmpCleanUpKcbCacheWithLock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 629 of file cmsubs.c.

References ASSERT, ASSERT_KEYBODY_LIST_EMPTY, CM_KCB_SUBKEY_HINT, CmpCleanUpKcbValueCache(), CmpDereferenceNameControlBlockWithLock(), CmpRemoveKeyControlBlock(), _CM_KEY_CONTROL_BLOCK::Delete, ExFreePoolWithTag, _CM_KEY_CONTROL_BLOCK::ExtFlags, _CM_KEY_CONTROL_BLOCK::IndexHint, _CM_KEY_CONTROL_BLOCK::NameBlock, _CM_KEY_CONTROL_BLOCK::ParentKcb, PROTECTED_POOL, _CM_KEY_CONTROL_BLOCK::RefCount, and SET_KCB_SIGNATURE.

Referenced by CmpCacheLookup(), CmpDereferenceKeyControlBlockWithLock(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

    00634                    :
    00635
    00636     Clean up all cached allocations that are associated to this key.
    00637     If the parent is still open just because of this one, Remove the parent as well.
    00638
    00639 Arguments:
    00640
    00641     KeyControlBlock - pointer to a key control block.
    00642
    00643 Return Value:
    00644
    00645     NONE.
    00646
    00647 --*/
    00648 {
    00649     PCM_KEY_CONTROL_BLOCK   Kcb;
    00650     PCM_KEY_CONTROL_BLOCK   ParentKcb;
    00651
    00652     Kcb = KeyControlBlock;
    00653
    00654     ASSERT(KeyControlBlock->RefCount == 0);
    00655
    00656     while (Kcb->RefCount == 0) {
    00657         //
    00658         // First, free allocations for Value/data.
    00659         //
    00660
    00661         CmpCleanUpKcbValueCache(Kcb);
    00662
    00663         //
    00664         // Free the kcb and dereference parentkcb and nameblock.
    00665         //
    00666
    00667         CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);
    00668
    00669         if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) {
    00670             //
    00671             // Now free the HintIndex allocation
    00672             //
    00673             ExFreePoolWithTag(Kcb->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL);
    00674         }
    00675
    00676         //
    00677         // Save the ParentKcb before we free the Kcb
    00678         //
    00679         ParentKcb = Kcb->ParentKcb;
    00680
    00681         //
    00682         // We cannot call CmpDereferenceKeyControlBlockWithLock so we can avoid recurrsion.
    00683         //
    00684
    00685         if (!Kcb->Delete) {
    00686             CmpRemoveKeyControlBlock(Kcb);
    00687         }
    00688         SET_KCB_SIGNATURE(Kcb, '4FmC');
    00689         ASSERT_KEYBODY_LIST_EMPTY(Kcb);
    00690         ExFreePoolWithTag(Kcb, CM_KCB_TAG | PROTECTED_POOL);
    00691
    00692         Kcb = ParentKcb;
    00693         Kcb->RefCount--;
    00694     }
    00695 }

VOID CmpCleanUpKcbValueCache | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 568 of file cmsubs.c.

References CM_KCB_NO_DELAY_CLOSE, CM_KCB_SYM_LINK_FOUND, CMP_GET_CACHED_ADDRESS, CMP_GET_CACHED_CELLDATA, CMP_IS_CELL_CACHED, CmpDereferenceKeyControlBlockWithLock(), CmpMakeSpecialPoolReadWrite, _CACHED_CHILD_LIST::Count, _CM_KEY_CONTROL_BLOCK::Delete, ExFreePool(), _CM_KEY_CONTROL_BLOCK::ExtFlags, HCELL_NIL, _CACHED_CHILD_LIST::RealKcb, _CM_KEY_CONTROL_BLOCK::RefCount, _CM_KEY_CONTROL_BLOCK::ValueCache, and _CACHED_CHILD_LIST::ValueList.

Referenced by CmDeleteValueKey(), CmpCleanUpKcbCacheWithLock(), CmpDoOpen(), CmpGetSymbolicLink(), CmRestoreKey(), and CmSetValueKey().

    00573                    :
    00574
    00575     Clean up cached value/data that are associated to this key.
    00576
    00577 Arguments:
    00578
    00579     KeyControlBlock - pointer to a key control block.
    00580
    00581 Return Value:
    00582
    00583     NONE.
    00584
    00585 --*/
    00586 {
    00587     ULONG i;
    00588     PULONG_PTR CachedList;
    00589     PCELL_DATA pcell;
    00590     ULONG      realsize;
    00591     BOOLEAN    small;
    00592
    00593     if (CMP_IS_CELL_CACHED(KeyControlBlock->ValueCache.ValueList)) {
    00594         CachedList = (PULONG_PTR) CMP_GET_CACHED_CELLDATA(KeyControlBlock->ValueCache.ValueList);
    00595         for (i = 0; i < KeyControlBlock->ValueCache.Count; i++) {
    00596             if (CMP_IS_CELL_CACHED(CachedList[i])) {
    00597
    00598                 // Trying to catch the BAD guy who writes over our pool.
    00599                 CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList[i]) );
    00600
    00601                 ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(CachedList[i]));
    00602
    00603             }
    00604         }
    00605
    00606         // Trying to catch the BAD guy who writes over our pool.
    00607         CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList) );
    00608
    00609         ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00610
    00611         // Mark the ValueList as NULL
    00612         KeyControlBlock->ValueCache.ValueList = HCELL_NIL;
    00613
    00614     } else if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00615         //
    00616         // This is a symbolic link key with symbolic name resolved.
    00617         // Dereference to its real kcb and clear the bit.
    00618         //
    00619         if ((KeyControlBlock->ValueCache.RealKcb->RefCount == 1) && !(KeyControlBlock->ValueCache.RealKcb->Delete)) {
    00620             KeyControlBlock->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
    00621         }
    00622         CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
    00623         KeyControlBlock->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    00624     }
    00625 }

VOID CmpCleanUpSubKeyInfo | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 537 of file cmsubs.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, CM_KCB_NO_SUBKEY, CM_KCB_SUBKEY_HINT, CM_KCB_SUBKEY_ONE, ExFreePoolWithTag, _CM_KEY_CONTROL_BLOCK::ExtFlags, _CM_KEY_CONTROL_BLOCK::IndexHint, and PROTECTED_POOL.

Referenced by CmDeleteKey(), CmpCreateLinkNode(), CmpDoCreate(), CmpSearchForOpenSubKeys(), and NtUnloadKey().

    00541                    :
    00542
    00543     Clean up the subkey information cache due to create or delete keys.
    00544     Registry is locked exclusively and no need to lock the KCB.
    00545
    00546 Arguments:
    00547
    00548     KeyControlBlock - pointer to a key control block.
    00549
    00550 Return Value:
    00551
    00552     NONE.
    00553
    00554 --*/
    00555 {
    00556     ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00557
    00558     if (KeyControlBlock->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT)) {
    00559         if (KeyControlBlock->ExtFlags & (CM_KCB_SUBKEY_HINT)) {
    00560             ExFreePoolWithTag(KeyControlBlock->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL);
    00561         }
    00562         KeyControlBlock->ExtFlags &= ~((CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT));
    00563     }
    00564 }

NTSTATUS CmpCloneHwProfile | ( | IN HANDLE | IDConfigDB,
|  | IN HANDLE | Parent,
|  | IN HANDLE | OldProfile,
|  | IN ULONG | OldProfileNumber,
|  | IN USHORT | DockingState,
|  | OUT PHANDLE | NewProfile,
|  | OUT PULONG | NewProfileNumber
| ) |

Definition at line 1869 of file hwprofil.c.

References ASSERT, CM_HARDWARE_PROFILE_STR_ALIASABLE, CM_HARDWARE_PROFILE_STR_CLONED, CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME, CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES, CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID, CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER, CML_BUGCHECK, CMLOG, CmpCopyTree, CmpCreateHwProfileFriendlyName(), CmpKeyObjectType, CmpLockRegistryExclusive(), CmpUnlockRegistry(), CMS_INIT, ExAllocatePool, ExFreePool(), ExUuidCreate(), FALSE, KernelMode, L, NT_SUCCESS, NtClose(), NtCreateKey(), NtOpenKey(), NtQuerySecurityObject(), NtQueryValueKey(), NtSetValueKey(), NTSTATUS(), NULL, ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, RtlFreeUnicodeString(), RtlInitUnicodeString(), RtlStringFromGUID(), TRUE, USHORT, and UUID.

Referenced by CmpCreateControlSet(), and CmSetAcpiHwProfile().

    01884       :
    01885
    01886     STATUS_SUCCESS - if the profile has been cloned, in which case the new
    01887         profile key has been opened for read / write privs.  The old profile
    01888         will be closed.
    01889
    01890     <unsuccessful> - for a given error.  NewProfile is invalid and the Old
    01891         Profile has also been closed.
    01892
    01893
    01894                 (Copied lovingly from CmpCloneControlSet)
    01895
    01896
    01897 --*/
    01898 {
    01899     NTSTATUS status = STATUS_SUCCESS;
    01900     UNICODE_STRING newProfileName;
    01901     UNICODE_STRING name;
    01902     UNICODE_STRING friendlyName;
    01903     UNICODE_STRING guidStr;
    01904     PCM_KEY_BODY oldProfileKey;
    01905     PCM_KEY_BODY newProfileKey;
    01906     OBJECT_ATTRIBUTES attributes;
    01907     PSECURITY_DESCRIPTOR security;
    01908     ULONG securityLength;
    01909     WCHAR nameBuffer [64];
    01910     HANDLE IDConfigDBEntry = NULL;
    01911     ULONG disposition;
    01912     ULONG value;
    01913     UUID  uuid;
    01914     PKEY_BASIC_INFORMATION keyBasicInfo;
    01915     PKEY_FULL_INFORMATION keyFullInfo;
    01916     PKEY_VALUE_FULL_INFORMATION keyValueInfo;
    01917     ULONG  length, profileSubKeys, i;
    01918     UCHAR  valueBuffer[256];
    01919     HANDLE hardwareProfiles=NULL;
    01920     HANDLE profileEntry=NULL;
    01921
    01922     PAGED_CODE ();
    01923
    01924     keyFullInfo  = (PKEY_FULL_INFORMATION)  valueBuffer;
    01925     keyBasicInfo = (PKEY_BASIC_INFORMATION) valueBuffer;
    01926     keyValueInfo = (PKEY_VALUE_FULL_INFORMATION) valueBuffer;
    01927
    01928     *NewProfile = 0;
    01929     *NewProfileNumber = OldProfileNumber;
    01930
    01931     //
    01932     // Find the new profile number.
    01933     //
    01934
    01935     while (*NewProfileNumber < 200) {
    01936         (*NewProfileNumber)++;
    01937
    01938         swprintf (nameBuffer, L"%04d", *NewProfileNumber);
    01939         RtlInitUnicodeString (&newProfileName, nameBuffer);
    01940
    01941         InitializeObjectAttributes(&attributes,
    01942                                    &newProfileName,
    01943                                    OBJ_CASE_INSENSITIVE,
    01944                                    Parent,
    01945                                    NULL);
    01946
    01947         status = NtOpenKey (NewProfile,
    01948                             KEY_READ | KEY_WRITE,
    01949                             &attributes);
    01950
    01951         if (NT_SUCCESS (status)) {
    01952             NtClose (*NewProfile);
    01953
    01954         } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
    01955             status = STATUS_SUCCESS;
    01956             break;
    01957
    01958         } else {
    01959             break;
    01960         }
    01961
    01962     }
    01963     if (!NT_SUCCESS (status)) {
    01964         CMLOG(CML_BUGCHECK, CMS_INIT) {
    01965             KdPrint(("CM: CmpCloneHwProfile error finding new profile key %08lx\n", status));
    01966         }
    01967         goto Exit;
    01968     }
    01969
    01970     //
    01971     // Get the security descriptor from the old key to create the new clone one.
    01972     //
    01973
    01974     status = NtQuerySecurityObject (OldProfile,
    01975                                     DACL_SECURITY_INFORMATION,
    01976                                     NULL,
    01977                                     0,
    01978                                     &securityLength);
    01979
    01980     if (STATUS_BUFFER_TOO_SMALL == status) {
    01981
    01982         security = ExAllocatePool (PagedPool, securityLength);
    01983
    01984         if (security != NULL) {
    01985             status = NtQuerySecurityObject(OldProfile,
    01986                                            DACL_SECURITY_INFORMATION,
    01987                                            security,
    01988                                            securityLength,
    01989                                            &securityLength);
    01990             if (!NT_SUCCESS (status)) {
    01991                 CMLOG(CML_BUGCHECK, CMS_INIT) {
    01992                     KdPrint(("CM: CmpCloneHwProfile"
    01993                              " - NtQuerySecurityObject failed %08lx\n", status));
    01994                 }
    01995                 ExFreePool(security);
    01996                 security=NULL;
    01997             }
    01998         }
    01999     } else {
    02000         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02001             KdPrint(("CM: CmpCloneHwProfile"
    02002                      " - NtQuerySecurityObject returned %08lx\n", status));
    02003         }
    02004         security=NULL;
    02005     }
    02006
    02007     //
    02008     // Create the new key
    02009     //
    02010     InitializeObjectAttributes  (&attributes,
    02011                                  &newProfileName,
    02012                                  OBJ_CASE_INSENSITIVE,
    02013                                  Parent,
    02014                                  security);
    02015
    02016     status = NtCreateKey (NewProfile,
    02017                           KEY_READ | KEY_WRITE,
    02018                           &attributes,
    02019                           0,
    02020                           NULL,
    02021                           0,
    02022                           &disposition);
    02023
    02024     if (NULL != security) {
    02025         ExFreePool (security);
    02026     }
    02027     if (!NT_SUCCESS (status)) {
    02028         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02029             KdPrint(("CM: CmpCloneHwProfile couldn't create Clone %08lx\n",status));
    02030         }
    02031         goto Exit;
    02032     }
    02033
    02034     //
    02035     // Check to make sure the key was created.  If it already exists,
    02036     // something is wrong.
    02037     //
    02038     if (disposition != REG_CREATED_NEW_KEY) {
    02039         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02040         //  KdPrint(("CM: CmpCloneHwProfile: Clone tree already exists!\n"));
    02041         }
    02042
    02043         //
    02044         // WARNNOTE:
    02045         //      If somebody somehow managed to create a key in our way,
    02046         //      they'll thwart duplication of the prestine.  Tough luck.
    02047         //      Claim it worked and go on.
    02048         //
    02049         status = STATUS_SUCCESS;
    02050         goto Exit;
    02051     }
    02052
    02053     //
    02054     // Create the IDConfigDB Entry
    02055     //
    02056     swprintf (nameBuffer, L"Hardware Profiles\\%04d", *NewProfileNumber);
    02057     RtlInitUnicodeString (&name, nameBuffer);
    02058
    02059     InitializeObjectAttributes  (&attributes,
    02060                                  &name,
    02061                                  OBJ_CASE_INSENSITIVE,
    02062                                  IDConfigDB,
    02063                                  NULL);
    02064
    02065     status = NtCreateKey (&IDConfigDBEntry,
    02066                           KEY_READ | KEY_WRITE,
    02067                           &attributes,
    02068                           0,
    02069                           NULL,
    02070                           0,
    02071                           &disposition);
    02072
    02073     if (!NT_SUCCESS (status)) {
    02074         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02075             KdPrint(("CM: CmpCloneHwProfile couldn't create Clone %08lx\n",status));
    02076         }
    02077         IDConfigDBEntry = NULL;
    02078         goto Exit;
    02079     }
    02080
    02081     //
    02082     // Determine the next PreferenceOrder for the new profile.  (The
    02083     // PrefenceOrder for the new profile will be incrementally next from the
    02084     // greatest PreferenceOrder value of all the current profiles; assumes
    02085     // current set of PreferenceOrder values is incremental)
    02086     //
    02087
    02088     //
    02089     // Open the Hardware Profiles key
    02090     //
    02091     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES);
    02092
    02093     InitializeObjectAttributes (&attributes,
    02094                                 &name,
    02095                                 OBJ_CASE_INSENSITIVE,
    02096                                 IDConfigDB,
    02097                                 NULL);
    02098     status = ZwOpenKey (&hardwareProfiles,
    02099                         KEY_READ,
    02100                         &attributes);
    02101
    02102     if (!NT_SUCCESS (status)) {
    02103         hardwareProfiles = NULL;
    02104         goto Exit;
    02105     }
    02106
    02107     //
    02108     // Find the number of profile Sub Keys
    02109     //
    02110     status = ZwQueryKey (hardwareProfiles,
    02111                          KeyFullInformation,
    02112                          valueBuffer,
    02113                          sizeof (valueBuffer),
    02114                          &length);
    02115
    02116     if (!NT_SUCCESS (status)) {
    02117         goto Exit;
    02118     }
    02119
    02120     //
    02121     // At very least, the Pristine and the new profile key we just created,
    02122     // should be there.
    02123     //
    02124     profileSubKeys = keyFullInfo->SubKeys;
    02125     ASSERT (1 < profileSubKeys);
    02126
    02127     //
    02128     // Initialize the highest PreferenceOrder value found to -1.
    02129     //
    02130     value = -1;
    02131
    02132     //
    02133     // Iterrate the profiles
    02134     //
    02135     for (i = 0; i < profileSubKeys; i++) {
    02136
    02137         //
    02138         // Enumerate all profile subkeys, noting their PreferenceOrder values.
    02139         //
    02140         status = ZwEnumerateKey (hardwareProfiles,
    02141                                  i,
    02142                                  KeyBasicInformation,
    02143                                  valueBuffer,
    02144                                  sizeof(valueBuffer) - sizeof (UNICODE_NULL), //term 0
    02145                                  &length);
    02146         if(!NT_SUCCESS(status)) {
    02147             break;
    02148         }
    02149
    02150         //
    02151         // Zero-terminate the subkey name just in case.
    02152         //
    02153         keyBasicInfo->Name[keyBasicInfo->NameLength/sizeof(WCHAR)] = 0;
    02154
    02155         //
    02156         // If this is the Pristine, or the NewProfile key, ignore it.
    02157         //
    02158         if ((!_wtoi(keyBasicInfo->Name)) ||
    02159             ((ULONG)(_wtoi(keyBasicInfo->Name)) == *NewProfileNumber)) {
    02160             continue;
    02161         }
    02162
    02163         //
    02164         // Open this profile key
    02165         //
    02166         name.Length = (USHORT) keyBasicInfo->NameLength;
    02167         name.MaximumLength = (USHORT) keyBasicInfo->NameLength + sizeof (UNICODE_NULL);
    02168         name.Buffer = keyBasicInfo->Name;
    02169
    02170         InitializeObjectAttributes (&attributes,
    02171                                     &name,
    02172                                     OBJ_CASE_INSENSITIVE,
    02173                                     hardwareProfiles,
    02174                                     NULL);
    02175         status = ZwOpenKey (&profileEntry,
    02176                             KEY_READ,
    02177                             &attributes);
    02178         if (!NT_SUCCESS (status)) {
    02179             profileEntry = NULL;
    02180             continue;
    02181         }
    02182
    02183         //
    02184         // Extract The PreferenceOrder value for this Profile.
    02185         //
    02186         RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER);
    02187         status = NtQueryValueKey(profileEntry,
    02188                                  &name,
    02189                                  KeyValueFullInformation,
    02190                                  valueBuffer,
    02191                                  sizeof(valueBuffer),
    02192                                  &length);
    02193
    02194         if (!NT_SUCCESS (status) || (keyValueInfo->Type != REG_DWORD)) {
    02195             //
    02196             // No PreferenceOrder; continue on as best we can
    02197             //
    02198             ZwClose(profileEntry);
    02199             profileEntry=NULL;
    02200             continue;
    02201         }
    02202
    02203         //
    02204         // If this is a the highest PreferenceOrder so far, reassign value to
    02205         // this PreferenceOrder, OR assign it this valid PreferenceOrder if
    02206         // value is still unassigned.
    02207         //
    02208         if (((*(PULONG) ((PUCHAR)keyValueInfo + keyValueInfo->DataOffset)) > value) ||
    02209             (value == -1)) {
    02210             value = (* (PULONG) ((PUCHAR)keyValueInfo + keyValueInfo->DataOffset));
    02211         }
    02212
    02213         ZwClose(profileEntry);
    02214         profileEntry=NULL;
    02215     }
    02216
    02217     //
    02218     // Increment value one above the greatest PreferenceOrder found.
    02219     // (If no other profiles were found, (value+=1) == 0, the most preferred
    02220     // profile)
    02221     //
    02222     value += 1;
    02223
    02224     //
    02225     // Give the new profile a preference order.
    02226     //
    02227     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER);
    02228     status = NtSetValueKey (IDConfigDBEntry,
    02229                             &name,
    02230                             0,
    02231                             REG_DWORD,
    02232                             &value,
    02233                             sizeof (value));
    02234
    02235     //
    02236     // Give the new profile a friendly name, based on the DockingState
    02237     //
    02238     status = CmpCreateHwProfileFriendlyName(IDConfigDB,
    02239                                             DockingState,
    02240                                             *NewProfileNumber,
    02241                                             &friendlyName);
    02242
    02243     if (NT_SUCCESS(status)) {
    02244         RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME);
    02245         status = NtSetValueKey (IDConfigDBEntry,
    02246                                 &name,
    02247                                 0,
    02248                                 REG_SZ,
    02249                                 friendlyName.Buffer,
    02250                                 friendlyName.Length + sizeof(UNICODE_NULL));
    02251         RtlFreeUnicodeString(&friendlyName);
    02252     }
    02253
    02254     //
    02255     // Set the aliasable flag on the new "cloned profile" to be false
    02256     //
    02257     value = FALSE;
    02258     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_ALIASABLE);
    02259     status = NtSetValueKey (IDConfigDBEntry,
    02260                             &name,
    02261                             0,
    02262                             REG_DWORD,
    02263                             &value,
    02264                             sizeof (value));
    02265
    02266     //
    02267     // Set the cloned profile on the new "cloned profile" to be true;
    02268     //
    02269     value = TRUE;
    02270     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_CLONED);
    02271     status = NtSetValueKey (IDConfigDBEntry,
    02272                             &name,
    02273                             0,
    02274                             REG_DWORD,
    02275                             &value,
    02276                             sizeof (value));
    02277
    02278     //
    02279     // Set the HwProfileGuid for the brand new profile
    02280     //
    02281
    02282     status = ExUuidCreate (&uuid);
    02283     if (NT_SUCCESS (status)) {
    02284
    02285         status = RtlStringFromGUID (&uuid, &guidStr);
    02286         if (NT_SUCCESS (status)) {
    02287             RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID);
    02288
    02289             status = NtSetValueKey (IDConfigDBEntry,
    02290                                     &name,
    02291                                     0,
    02292                                     REG_SZ,
    02293                                     guidStr.Buffer,
    02294                                     guidStr.MaximumLength);
    02295
    02296             RtlFreeUnicodeString(&guidStr);
    02297         } else {
    02298             //
    02299             // What's a fella to do?
    02300             // let's just go on.
    02301             //
    02302             status = STATUS_SUCCESS;
    02303         }
    02304
    02305     } else {
    02306         //
    02307         // let's just go on.
    02308         //
    02309         status = STATUS_SUCCESS;
    02310     }
    02311
    02312
    02313     //
    02314     // Clone the key
    02315     //
    02316     // (Copied lovingly from CmpCloneControlSet)
    02317     //
    02318     //
    02319     status = ObReferenceObjectByHandle (OldProfile,
    02320                                         KEY_READ,
    02321                                         CmpKeyObjectType,
    02322                                         KernelMode,
    02323                                         (PVOID *)(&oldProfileKey),
    02324                                         NULL);
    02325
    02326     if (!NT_SUCCESS(status)) {
    02327         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02328             KdPrint(("CM: CmpCloneHWProfile: couldn't reference CurrentHandle %08lx\n",
    02329                      status));
    02330         }
    02331         goto Exit;
    02332     }
    02333
    02334     ObReferenceObjectByHandle (*NewProfile,
    02335                                KEY_WRITE,
    02336                                CmpKeyObjectType,
    02337                                KernelMode,
    02338                                (PVOID *)(&newProfileKey),
    02339                                NULL);
    02340
    02341     if (!NT_SUCCESS(status)) {
    02342         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02343             KdPrint(("CM: CmpCloneHWProfile: couldn't reference CurrentHandle %08lx\n",
    02344                      status));
    02345         }
    02346         goto Exit;
    02347     }
    02348
    02349     CmpLockRegistryExclusive();
    02350
    02351     //
    02352     // Note: This copy tree command does not copy the values in the
    02353     // root keys.  We are relying on this, since the values stored there
    02354     // are things like "pristine" which we do not wish to have moved to the
    02355     // new tree.
    02356     //
    02357     if (CmpCopyTree(oldProfileKey->KeyControlBlock->KeyHive,
    02358                     oldProfileKey->KeyControlBlock->KeyCell,
    02359                     newProfileKey->KeyControlBlock->KeyHive,
    02360                     newProfileKey->KeyControlBlock->KeyCell)) {
    02361         //
    02362         // Set the max subkey name property for the new target key.
    02363         //
    02364         newProfileKey->KeyControlBlock->KeyNode->MaxNameLen =
    02365             oldProfileKey->KeyControlBlock->KeyNode->MaxNameLen;
    02366         status = STATUS_SUCCESS;
    02367     } else {
    02368         CMLOG(CML_BUGCHECK, CMS_INIT) {
    02369             KdPrint(("CM: CmpCloneHwProfile: tree copy failed.\n"));
    02370         }
    02371         status = STATUS_REGISTRY_CORRUPT;
    02372     }
    02373     CmpUnlockRegistry();
    02374
    02375
    02376 Exit:
    02377     NtClose (OldProfile);
    02378     if (IDConfigDBEntry) {
    02379         NtClose (IDConfigDBEntry);
    02380     }
    02381     if (hardwareProfiles) {
    02382         NtClose (hardwareProfiles);
    02383     }
    02384     if (!NT_SUCCESS (status)) {
    02385         if (*NewProfile) {
    02386             NtClose (*NewProfile);
    02387         }
    02388     }
    02389
    02390     return status;
    02391 }

VOID CmpCloseKeyObject | ( | IN PEPROCESS Process | OPTIONAL,
|  | IN PVOID | Object,
|  | IN ACCESS_MASK | GrantedAccess,
|  | IN ULONG | ProcessHandleCount,
|  | IN ULONG | SystemHandleCount
| ) |

Definition at line 28 of file cmclose.c.

References CML_MAJOR, CmLockHive, CMLOG, CmpLockRegistry(), CmpPostNotify(), CmpUnlockRegistry(), CMS_NTAPI, CMS_POOL, CmUnlockHive, FALSE, KEY_BODY_TYPE, _CM_KEY_BODY::KeyControlBlock, _CM_KEY_CONTROL_BLOCK::KeyHive, _CM_KEY_BODY::NotifyBlock, NULL, PAGED_CODE, PCM_NOTIFY_BLOCK, _CM_NOTIFY_BLOCK::PostList, and _CM_KEY_BODY::Type.

Referenced by CmpCreateObjectTypes().

    00037                    :
    00038
    00039     This routine interfaces to the NT Object Manager.  It is invoked when
    00040     a Key object (or Key Root object) is closed.
    00041
    00042     It's function is to do cleanup processing by waking up any notifies
    00043     pending on the handle.  This keeps the key object from hanging around
    00044     forever because a synchronous notify is stuck on it somewhere.
    00045
    00046     All other cleanup, in particular, the freeing of storage, will be
    00047     done in CmpDeleteKeyObject.
    00048
    00049 Arguments:
    00050
    00051     Process - ignored
    00052
    00053     Object - supplies a pointer to a KeyRoot or Key, thus -> KEY_BODY.
    00054
    00055     GrantedAccess, ProcessHandleCount, SystemHandleCount - ignored
    00056
    00057 Return Value:
    00058
    00059     NONE.
    00060
    00061 --*/
    00062 {
    00063     PCM_KEY_BODY        KeyBody;
    00064     PCM_NOTIFY_BLOCK    NotifyBlock;
    00065
    00066     PAGED_CODE();
    00067     CMLOG(CML_MAJOR, CMS_NTAPI|CMS_POOL) {
    00068         KdPrint(("CmpCloseKeyObject: Object = %08lx\n", Object));
    00069     }
    00070
    00071     if( SystemHandleCount > 1 ) {
    00072         //
    00073         // There are still has open handles on this key. Do nothing
    00074         //
    00075         return;
    00076     }
    00077
    00078     CmpLockRegistry();
    00079
    00080     KeyBody = (PCM_KEY_BODY)Object;
    00081
    00082     //
    00083     // Check the type, it will be something else if we are closing a predefined
    00084     // handle key
    00085     //
    00086     if (KeyBody->Type == KEY_BODY_TYPE) {
    00087         //
    00088         // Clean up any outstanding notifies attached to the KeyBody
    00089         //
    00090         if (KeyBody->NotifyBlock != NULL) {
    00091             //
    00092             // Post all PostBlocks waiting on the NotifyBlock
    00093             //
    00094             NotifyBlock = KeyBody->NotifyBlock;
    00095             if (IsListEmpty(&(NotifyBlock->PostList)) == FALSE) {
    00096                 CmLockHive((PCMHIVE)(KeyBody->KeyControlBlock->KeyHive));
    00097                 CmpPostNotify(NotifyBlock,
    00098                               NULL,
    00099                               0,
    00100                               STATUS_NOTIFY_CLEANUP,
    00101                               NULL);
    00102                 CmUnlockHive((PCMHIVE)(KeyBody->KeyControlBlock->KeyHive));
    00103             }
    00104         }
    00105     }
    00106
    00107     CmpUnlockRegistry();
    00108     return;
    00109 }
    }

LONG CmpCompareCompressedName | ( | IN PUNICODE_STRING | SearchName,
|  | IN PWCHAR | CompressedName,
|  | IN ULONG | NameLength
| ) |

Definition at line 195 of file cmname.c.

References RtlUpcaseUnicodeChar(), and USHORT.

Referenced by CmpCacheLookup(), CmpDoCompareKeyName(), CmpFindNameInList(), CmpFindValueByNameFromCache(), and CmpGetNameControlBlock().

    00203                    :
    00204
    00205     Compares a compressed registry string to a Unicode string.  Does a case-insensitive
    00206     comparison.
    00207
    00208 Arguments:
    00209
    00210     SearchName - Supplies the Unicode string to be compared
    00211
    00212     CompressedName - Supplies the compressed string to be compared
    00213
    00214     NameLength - Supplies the length of the compressed string
    00215
    00216 Return Value:
    00217
    00218     0 = SearchName == CompressedName (of Cell)
    00219
    00220     < 0 = SearchName < CompressedName
    00221
    00222     > 0 = SearchName > CompressedName
    00223
    00224 --*/
    00225
    00226 {
    00227     WCHAR *s1;
    00228     UCHAR *s2;
    00229     USHORT n1, n2;
    00230     WCHAR c1;
    00231     WCHAR c2;
    00232     LONG cDiff;
    00233
    00234     s1 = SearchName->Buffer;
    00235     s2 = (UCHAR *)CompressedName;
    00236     n1 = (USHORT )(SearchName->Length / sizeof(WCHAR));
    00237     n2 = (USHORT )(NameLength);
    00238     while (n1 && n2) {
    00239         c1 = *s1++;
    00240         c2 = (WCHAR)(*s2++);
    00241
    00242         c1 = RtlUpcaseUnicodeChar(c1);
    00243         c2 = RtlUpcaseUnicodeChar(c2);
    00244
    00245         if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
    00246             return( cDiff );
    00247         }
    00248
    00249         n1--;
    00250         n2--;
    00251     }
    00252
    00253     return( n1 - n2 );
    00254 }

USHORT CmpCompressedNameSize | ( | IN PWCHAR | Name,
|  | IN ULONG | Length
| ) |

Definition at line 121 of file cmname.c.

References USHORT.

Referenced by CmpAddDriverToList(), CmpAddSubKey(), CmpFindProfileOption(), CmpInitializeKeyNameString(), CmpInitializeValueNameString(), CmpMarkIndexDirty(), and CmpRemoveSubKey().

    00128                    :
    00129
    00130     Computes the length of the unicode string that the given compressed name
    00131     expands into.
    00132
    00133 Arguments:
    00134
    00135     Name - Supplies the compressed name.
    00136
    00137     Length - Supplies the length in bytes of the compressed name
    00138
    00139 Return Value:
    00140
    00141     The number of bytes of storage required to hold the Unicode expanded name.
    00142
    00143 --*/
    00144
    00145 {
    00146     return((USHORT)Length*sizeof(WCHAR));
    00147 }

VOID CmpComputeGlobalQuotaAllowed | ( | VOID |  | ) |

Definition at line 293 of file cmgquota.c.

References CM_DEFAULT_RATIO, CM_LIMIT_RATIO, CM_MINIMUM_GLOBAL_QUOTA, CM_REGISTRY_WARNING_LEVEL, CM_WRAP_LIMIT, CmpGlobalQuota, CmpGlobalQuotaWarning, CmRegistrySizeLimit, CmRegistrySizeLimitLength, CmRegistrySizeLimitType, and MmSizeOfPagedPoolInBytes.

Referenced by CmInitSystem1().

    00299                    :
    00300
    00301     Compute CmpGlobalQuota based on:
    00302         (a) Size of paged pool
    00303         (b) Explicit user registry commands to set registry GQ
    00304
    00305 Return Value:
    00306
    00307     NONE.
    00308
    00309 --*/
    00310
    00311 {
    00312     ULONG   PagedLimit;
    00313
    00314     PagedLimit = CM_LIMIT_RATIO(MmSizeOfPagedPoolInBytes);
    00315
    00316     if ((CmRegistrySizeLimitLength != 4) ||
    00317         (CmRegistrySizeLimitType != REG_DWORD) ||
    00318         (CmRegistrySizeLimit == 0))
    00319     {
    00320         //
    00321         // If no value at all, or value of wrong type, or set to
    00322         // zero, use internally computed default
    00323         //
    00324         CmpGlobalQuota = MmSizeOfPagedPoolInBytes / CM_DEFAULT_RATIO;
    00325
    00326     } else if (CmRegistrySizeLimit >= PagedLimit) {
    00327         //
    00328         // If more than computed upper bound, use computed upper bound
    00329         //
    00330         CmpGlobalQuota = PagedLimit;
    00331
    00332     } else {
    00333         //
    00334         // Use the set size
    00335         //
    00336         CmpGlobalQuota = CmRegistrySizeLimit;
    00337
    00338     }
    00339
    00340     if (CmpGlobalQuota > CM_WRAP_LIMIT) {
    00341         CmpGlobalQuota = CM_WRAP_LIMIT;
    00342     }
    00343     if (CmpGlobalQuota < CM_MINIMUM_GLOBAL_QUOTA) {
    00344         CmpGlobalQuota = CM_MINIMUM_GLOBAL_QUOTA;
    00345     }
    00346
    00347     CmpGlobalQuotaWarning = CM_REGISTRY_WARNING_LEVEL * (CmpGlobalQuota / 100);
    00348
    00349     return;
    00350 }

PUNICODE_STRING CmpConstructName | ( | PCM_KEY_CONTROL_BLOCK | kcb | ) |

Definition at line 699 of file cmsubs.c.

References _CM_NAME_CONTROL_BLOCK::Compressed, ExAllocatePoolWithTag, kcb(), _CM_NAME_CONTROL_BLOCK::Name, _CM_KEY_CONTROL_BLOCK::NameBlock, _CM_NAME_CONTROL_BLOCK::NameLength, PagedPool, _CM_KEY_CONTROL_BLOCK::ParentKcb, PROTECTED_POOL, and USHORT.

Referenced by CmpGetSymbolicLink(), CmpLoadHiveVolatile(), CmpQueryKeyName(), and CmQueryKey().

    00704                    :
    00705
    00706     Construct the name given a kcb.
    00707
    00708 Arguments:
    00709
    00710     kcb - Kcb for the key
    00711
    00712 Return Value:
    00713
    00714     Pointer to the unicode string constructed.
    00715     Caller is responsible to free this storage space.
    00716
    00717 --*/
    00718 {
    00719     PUNICODE_STRING FullName;
    00720     PCM_KEY_CONTROL_BLOCK TmpKcb;
    00721     USHORT Length;
    00722     USHORT size;
    00723     USHORT i;
    00724     USHORT BeginPosition;
    00725     WCHAR *w1, *w2;
    00726     UCHAR *u2;
    00727
    00728     //
    00729     // Calculate the total string length.
    00730     //
    00731     Length = 0;
    00732     TmpKcb = kcb;
    00733     while (TmpKcb) {
    00734         if (TmpKcb->NameBlock->Compressed) {
    00735             Length += TmpKcb->NameBlock->NameLength * sizeof(WCHAR);
    00736         } else {
    00737             Length += TmpKcb->NameBlock->NameLength;
    00738         }
    00739         //
    00740         // Add the sapce for OBJ_NAME_PATH_SEPARATOR;
    00741         //
    00742         Length += sizeof(WCHAR);
    00743
    00744         TmpKcb = TmpKcb->ParentKcb;
    00745     }
    00746
    00747     //
    00748     // Allocate the pool for the unicode string
    00749     //
    00750     size = sizeof(UNICODE_STRING) + Length;
    00751
    00752     FullName = (PUNICODE_STRING) ExAllocatePoolWithTag(PagedPool,
    00753                                                        size,
    00754                                                        CM_NAME_TAG | PROTECTED_POOL);
    00755
    00756     if (FullName) {
    00757         FullName->Buffer = (USHORT *) ((ULONG_PTR) FullName + sizeof(UNICODE_STRING));
    00758         FullName->Length = Length;
    00759         FullName->MaximumLength = Length;
    00760
    00761         //
    00762         // Now fill the name into the buffer.
    00763         //
    00764         TmpKcb = kcb;
    00765         BeginPosition = Length;
    00766
    00767         while (TmpKcb) {
    00768             //
    00769             // Calculate the begin position of each subkey. Then fill in the char.
    00770             //
    00771             //
    00772             if (TmpKcb->NameBlock->Compressed) {
    00773                 BeginPosition -= (TmpKcb->NameBlock->NameLength + 1) * sizeof(WCHAR);
    00774                 w1 = &(FullName->Buffer[BeginPosition/sizeof(WCHAR)]);
    00775                 *w1 = OBJ_NAME_PATH_SEPARATOR;
    00776                 w1++;
    00777
    00778                 u2 = (UCHAR *) &(TmpKcb->NameBlock->Name[0]);
    00779
    00780                 for (i=0; i<TmpKcb->NameBlock->NameLength; i++) {
    00781                     *w1 = (WCHAR)(*u2);
    00782                     w1++;
    00783                     u2++;
    00784                 }
    00785             } else {
    00786                 BeginPosition -= (TmpKcb->NameBlock->NameLength + sizeof(WCHAR));
    00787                 w1 = &(FullName->Buffer[BeginPosition/sizeof(WCHAR)]);
    00788                 *w1 = OBJ_NAME_PATH_SEPARATOR;
    00789                 w1++;
    00790
    00791                 w2 = TmpKcb->NameBlock->Name;
    00792
    00793                 for (i=0; i<TmpKcb->NameBlock->NameLength; i=i+sizeof(WCHAR)) {
    00794                     *w1 = *w2;
    00795                     w1++;
    00796                     w2++;
    00797                 }
    00798             }
    00799             TmpKcb = TmpKcb->ParentKcb;
    00800         }
    00801     }
    00802     return (FullName);
    00803 }

HCELL_INDEX CmpCopyCell | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceCell,
|  | PHHIVE | TargetHive,
|  | HSTORAGE_TYPE | Type
| ) |

Definition at line 1009 of file cmtrecpy.c.

References CML_MINOR, CMLOG, CMS_SAVRES, HCELL_INDEX, HCELL_NIL, HvAllocateCell(), HvGetCell, and HvGetCellSize().

Referenced by CmpCopyKeyPartial(), CmpCopyValue(), and CmpSyncKeyValues().

    01017                    :
    01018
    01019     Copy SourceHive.SourceCell to TargetHive.TargetCell.
    01020
    01021 Arguments:
    01022
    01023     SourceHive - pointer to hive control structure for source
    01024
    01025     SourceCell - index of cell to copy from
    01026
    01027     TargetHive - pointer to hive control structure for target
    01028
    01029     Type - storage type (stable or volatile) of new cell
    01030
    01031 Return Value:
    01032
    01033     HCELL_INDEX of new cell, or HCELL_NIL if failure.
    01034
    01035 --*/
    01036 {
    01037     PVOID   psource;
    01038     PVOID   ptarget;
    01039     ULONG   size;
    01040     HCELL_INDEX newcell;
    01041
    01042     CMLOG(CML_MINOR, CMS_SAVRES) {
    01043         KdPrint(("CmpCopyCell:\n"));
    01044         KdPrint(("\tSourceHive=%08lx SourceCell=%08lx\n",SourceHive,SourceCell));
    01045         KdPrint(("\tTargetHive=%08lx\n",TargetHive));
    01046     }
    01047
    01048     psource = HvGetCell(SourceHive, SourceCell);
    01049     size = HvGetCellSize(SourceHive, psource);
    01050
    01051     newcell = HvAllocateCell(TargetHive, size, Type);
    01052     if (newcell == HCELL_NIL) {
    01053         return HCELL_NIL;
    01054     }
    01055
    01056     ptarget = HvGetCell(TargetHive, newcell);
    01057
    01058     RtlCopyMemory(ptarget, psource, size);
    01059
    01060     return newcell;
    01061 }

VOID CmpCopyCompressedName | ( | IN PWCHAR | Destination,
|  | IN ULONG | DestinationLength,
|  | IN PWCHAR | Source,
|  | IN ULONG | SourceLength
| ) |

Definition at line 151 of file cmname.c.

Referenced by CmpAddDriverToList(), CmpAddSubKey(), CmpFindProfileOption(), CmpGetHiveName(), CmpInitializeKeyNameString(), CmpInitializeValueNameString(), CmpLoadHiveVolatile(), CmpMarkIndexDirty(), CmpQueryKeyData(), CmpQueryKeyValueData(), and CmpRemoveSubKey().

    00160                    :
    00161
    00162     Copies a compressed name from the registry and expands it to Unicode.
    00163
    00164 Arguments:
    00165
    00166     Destination - Supplies the destination Unicode buffer
    00167
    00168     DestinationLength - Supplies the max length of the destination buffer in bytes
    00169
    00170     Source - Supplies the compressed string.
    00171
    00172     SourceLength - Supplies the length of the compressed string in bytes
    00173
    00174 Return Value:
    00175
    00176     None.
    00177
    00178 --*/
    00179
    00180 {
    00181     ULONG i;
    00182     ULONG Chars;
    00183
    00184     Chars = (DestinationLength/sizeof(WCHAR) < SourceLength)
    00185              ? DestinationLength/sizeof(WCHAR)
    00186              : SourceLength;
    00187
    00188     for (i=0;i<Chars;i++) {
    00189         Destination[i] = (WCHAR)(((PUCHAR)Source)[i]);
    00190     }
    00191 }

HCELL_INDEX CmpCopyKeyPartial | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceKeyCell,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | Parent,
|  | BOOLEAN | CopyValues
| ) |

Definition at line 686 of file cmtrecpy.c.

References _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CML_MINOR, CMLOG, CmpAssignSecurityDescriptor(), CmpCopyCell(), CmpCopyValue(), CMS_SAVRES, _CHILD_LIST::Count, _CM_KEY_SECURITY::Descriptor, FALSE, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, KEY_COMP_NAME, KEY_HIVE_ENTRY, KEY_NO_DELETE, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyNode, _CELL_DATA::_u::KeySecurity, _CHILD_LIST::List, NT_SUCCESS, NTSTATUS(), _CM_KEY_NODE::Parent, _CM_KEY_NODE::Security, Stable, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmpCopySyncTree2(), CmpLoadHiveVolatile(), CmRestoreKey(), CmSaveKey(), and CmSaveMergedKeys().

    00695                    :
    00696
    00697     Copy a key body and all of its values, but NOT its subkeylist or
    00698     subkey entries.  SubKeyList.Count will be set to 0.
    00699
    00700 Arguments:
    00701
    00702     SourceHive - pointer to hive control structure for source
    00703
    00704     SourceKeyCell - value entry being copied
    00705
    00706     TargetHive - pointer to hive control structure for target
    00707
    00708     Parent - parent value to set into newly created key body
    00709
    00710     CopyValues - if FALSE value entries will not be copied, if TRUE, they will
    00711
    00712 Return Value:
    00713
    00714     HCELL_INDEX - Cell of body of new key entry, or HCELL_NIL
    00715         if some error.
    00716
    00717 --*/
    00718 {
    00719     NTSTATUS    status;
    00720     HCELL_INDEX newkey = HCELL_NIL;
    00721     HCELL_INDEX newclass = HCELL_NIL;
    00722     HCELL_INDEX newsecurity = HCELL_NIL;
    00723     HCELL_INDEX newlist = HCELL_NIL;
    00724     HCELL_INDEX newvalue;
    00725     BOOLEAN success = FALSE;
    00726     ULONG   i;
    00727     PCELL_DATA psrckey;
    00728     PCM_KEY_NODE ptarkey;
    00729     PCELL_DATA psrclist;
    00730     PCELL_DATA ptarlist;
    00731     PCELL_DATA psrcsecurity;
    00732     HCELL_INDEX security;
    00733     HCELL_INDEX class;
    00734     ULONG   classlength;
    00735     ULONG   count;
    00736     ULONG   Type;
    00737
    00738     CMLOG(CML_MINOR, CMS_SAVRES) {
    00739         KdPrint(("CmpCopyKeyPartial:\n"));
    00740         KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceKeyCell));
    00741         KdPrint(("\tTHive=%08lx\n",TargetHive));
    00742     }
    00743
    00744
    00745     //
    00746     // get description of source
    00747     //
    00748     if (Parent == HCELL_NIL) {
    00749         //
    00750         // This is a root node we are creating, so don't make it volatile.
    00751         //
    00752         Type = Stable;
    00753     } else {
    00754         Type = HvGetCellType(Parent);
    00755     }
    00756     psrckey = HvGetCell(SourceHive, SourceKeyCell);
    00757     security = psrckey->u.KeyNode.Security;
    00758     class = psrckey->u.KeyNode.Class;
    00759     classlength = psrckey->u.KeyNode.ClassLength;
    00760
    00761     //
    00762     // Allocate and copy the body
    00763     //
    00764     newkey = CmpCopyCell(SourceHive, SourceKeyCell, TargetHive, Type);
    00765     if (newkey == HCELL_NIL) {
    00766         goto DoFinally;
    00767     }
    00768
    00769     //
    00770     // Allocate and copy class
    00771     //
    00772     if (classlength > 0) {
    00773         newclass = CmpCopyCell(SourceHive, class, TargetHive, Type);
    00774         if (newclass == HCELL_NIL) {
    00775             goto DoFinally;
    00776         }
    00777     }
    00778
    00779     //
    00780     // Fill in the target body
    00781     //
    00782     ptarkey = (PCM_KEY_NODE)HvGetCell(TargetHive, newkey);
    00783
    00784     ptarkey->Class = newclass;
    00785     ptarkey->Security = HCELL_NIL;
    00786     ptarkey->SubKeyLists[Stable] = HCELL_NIL;
    00787     ptarkey->SubKeyLists[Volatile] = HCELL_NIL;
    00788     ptarkey->SubKeyCounts[Stable] = 0;
    00789     ptarkey->SubKeyCounts[Volatile] = 0;
    00790     ptarkey->Parent = Parent;
    00791
    00792     ptarkey->Flags = (psrckey->u.KeyNode.Flags & KEY_COMP_NAME);
    00793     if (Parent == HCELL_NIL) {
    00794         ptarkey->Flags |= KEY_HIVE_ENTRY + KEY_NO_DELETE;
    00795     }
    00796
    00797     //
    00798     // Allocate and copy security
    00799     //
    00800     psrcsecurity = HvGetCell(SourceHive, security);
    00801
    00802     status = CmpAssignSecurityDescriptor(TargetHive,
    00803                                          newkey,
    00804                                          ptarkey,
    00805                                          &(psrcsecurity->u.KeySecurity.Descriptor));
    00806     if (!NT_SUCCESS(status)) {
    00807         goto DoFinally;
    00808     }
    00809
    00810
    00811     //
    00812     // Set up the value list
    00813     //
    00814     count = psrckey->u.KeyNode.ValueList.Count;
    00815
    00816     if ((count == 0) || (CopyValues == FALSE)) {
    00817         ptarkey->ValueList.List = HCELL_NIL;
    00818         ptarkey->ValueList.Count = 0;
    00819         success = TRUE;
    00820     } else {
    00821
    00822         psrclist = HvGetCell(SourceHive, psrckey->u.KeyNode.ValueList.List);
    00823
    00824         newlist = HvAllocateCell(
    00825                     TargetHive,
    00826                     count * sizeof(HCELL_INDEX),
    00827                     Type
    00828                     );
    00829         if (newlist == HCELL_NIL) {
    00830             goto DoFinally;
    00831         }
    00832         ptarkey->ValueList.List = newlist;
    00833         ptarlist = HvGetCell(TargetHive, newlist);
    00834
    00835
    00836         //
    00837         // Copy the values
    00838         //
    00839         for (i = 0; i < count; i++) {
    00840
    00841             newvalue = CmpCopyValue(
    00842                             SourceHive,
    00843                             psrclist->u.KeyList[i],
    00844                             TargetHive,
    00845                             Type
    00846                             );
    00847
    00848             if (newvalue != HCELL_NIL) {
    00849
    00850                 ptarlist->u.KeyList[i] = newvalue;
    00851
    00852             } else {
    00853
    00854                 for (; i > 0; i--) {
    00855                     HvFreeCell(
    00856                         TargetHive,
    00857                         ptarlist->u.KeyList[i - 1]
    00858                         );
    00859                 }
    00860                 goto DoFinally;
    00861             }
    00862         }
    00863         success = TRUE;
    00864     }
    00865
    00866 DoFinally:
    00867     if (success == FALSE) {
    00868
    00869         if (newlist != HCELL_NIL) {
    00870             HvFreeCell(TargetHive, newlist);
    00871         }
    00872
    00873         if (newsecurity != HCELL_NIL) {
    00874             HvFreeCell(TargetHive, newsecurity);
    00875         }
    00876
    00877         if (newclass != HCELL_NIL) {
    00878             HvFreeCell(TargetHive, newclass);
    00879         }
    00880
    00881         if (newkey != HCELL_NIL) {
    00882             HvFreeCell(TargetHive, newkey);
    00883         }
    00884
    00885         return HCELL_NIL;
    00886
    00887     } else {
    00888
    00889         return newkey;
    00890     }
    00891 }

USHORT CmpCopyName | ( | IN PHHIVE | Hive,
|  | IN PWCHAR | Destination,
|  | IN PUNICODE_STRING | Source
| ) |

Definition at line 74 of file cmname.c.

References Hive, USHORT, and _HHIVE::Version.

Referenced by CmpCreateLinkNode(), CmpCreateRootNode(), CmpDoCreateChild(), and CmpSetValueKeyNew().

    00082                    :
    00083
    00084     Copies the given unicode name into the registry, applying any relevant compression
    00085     at the same time.
    00086
    00087 Arguments:
    00088
    00089     Hive - supplies the hive control structure (For version checking)
    00090
    00091     Destination - Supplies the destination of the given string.
    00092
    00093     Source - Supplies the unicode string to copy into the registry.
    00094
    00095 Return Value:
    00096
    00097     Number of bytes of storage copied
    00098
    00099 --*/
    00100
    00101 {
    00102     ULONG i;
    00103
    00104     if (Hive->Version==1) {
    00105         RtlCopyMemory(Destination,Source->Buffer, Source->Length);
    00106         return(Source->Length);
    00107     }
    00108
    00109     for (i=0;i<Source->Length/sizeof(WCHAR);i++) {
    00110         if ((USHORT)Source->Buffer[i] > (UCHAR)-1) {
    00111             RtlCopyMemory(Destination,Source->Buffer, Source->Length);
    00112             return(Source->Length);
    00113         }
    00114         ((PUCHAR)Destination)[i] = (UCHAR)(Source->Buffer[i]);
    00115     }
    00116     return(Source->Length / sizeof(WCHAR));
    00117 }

BOOLEAN CmpCopySyncTree | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceCell,
|  | PHHIVE | TargetHive,
|  | HCELL_INDEX | TargetCell,
|  | BOOLEAN | CopyVolatile,
|  | CMP_COPY_TYPE | CopyType
| ) |

Definition at line 127 of file cmtrecpy.c.

References CML_MAJOR, CMLOG, CMP_INITIAL_STACK_SIZE, CmpCopySyncTree2(), CMS_SAVRES, ExAllocatePool, ExFreePool(), FALSE, NULL, PagedPool, and PCMP_COPY_STACK_ENTRY.

    00137                    :
    00138
    00139     This routine can perform two distinct (yet similar) tasks:
    00140     a tree copy or a tree synchronization (sync). Which task
    00141     is performed is determined by the TreeSync parameter.
    00142
    00143     For both operations:
    00144     --------------------
    00145
    00146     The source root key and target root key must exist in advance.
    00147     These root nodes and their value entries will NOT be copied/synced.
    00148
    00149     NOTE:   Volatile keys are only copied/synced if the CopyVolatile
    00150             parameter is set to true.
    00151
    00152
    00153     For a tree copy:
    00154     ----------------
    00155
    00156     A tree is copied from source to destination. The subkeys
    00157     of the source root key and the full trees under those
    00158     subkeys will be copied to a new tree at target root key.
    00159
    00160     NOTE:   If this call fails part way through, it will NOT undo
    00161             any successfully completed key copies, thus a partial
    00162             tree copy CAN occur.
    00163
    00164     For a tree sync:
    00165     ----------------
    00166
    00167     The target tree is synchronized with the source tree. It is
    00168     assumed that for a certain period of the time the target tree
    00169     has remained unmodified while modifications may have been made
    00170     to the source tree. During a sync, any such modifications
    00171     to the source tree are made to the target tree. Thus, at the
    00172     end of a successful sync, the target tree is identical to the
    00173     source tree.
    00174
    00175     Since only things that have changed in the source tree
    00176     are modified in the target tree, a sync operation is far
    00177     more efficient than the delete/copy operations necessary
    00178     to accomplish the same results.
    00179
    00180     NOTE: It is assumed that no open handles are held
    00181           on any target tree keys. Registry in-memory data
    00182           structures may be corrupted if this is not true.
    00183
    00184 Arguments:
    00185
    00186     SourceHive - pointer to hive control structure for source
    00187
    00188     SourceCell - index of cell at root of tree to copy/sync
    00189
    00190     TargetHive - pointer to hive control structure for target
    00191
    00192     TargetCell - pointer to cell at root of target tree
    00193
    00194     CopyVolatile - indicates whether volatile keys should be
    00195                    copied/synced.
    00196
    00197     CopyType - indicates the type of the copy operation:
    00198                 Copy  - A copy is requested
    00199                 Sync  - A sync is requested
    00200                 Merge - A merge is requested i.e.:
    00201                     1. the target nodes that are not present on the source tree are not
    00202                     deleted.
    00203                     2. the target nodes that are present in the source tree gets overrided
    00204                     no matter what the LastWriteTime value is.
    00205 Return Value:
    00206
    00207     BOOLEAN - Result code from call, among the following:
    00208         TRUE - it worked
    00209         FALSE - the tree copy/sync was not completed (though more than 0
    00210                 keys may have been copied/synced)
    00211
    00212 --*/
    00213 {
    00214     BOOLEAN result;
    00215     PCMP_COPY_STACK_ENTRY   CmpCopyStack;
    00216
    00217     CMLOG(CML_MAJOR, CMS_SAVRES) {
    00218         KdPrint(("CmpCopyTree:\n"));
    00219     }
    00220
    00221     CmpCopyStack = ExAllocatePool(
    00222                         PagedPool,
    00223                         sizeof(CMP_COPY_STACK_ENTRY)*CMP_INITIAL_STACK_SIZE
    00224                         );
    00225     if (CmpCopyStack == NULL) {
    00226         return FALSE;
    00227     }
    00228     CmpCopyStack[0].SourceCell = SourceCell;
    00229     CmpCopyStack[0].TargetCell = TargetCell;
    00230
    00231     result = CmpCopySyncTree2(
    00232                 CmpCopyStack,
    00233                 CMP_INITIAL_STACK_SIZE,
    00234                 0,
    00235                 SourceHive,
    00236                 TargetHive,
    00237                 CopyVolatile,
    00238                 CopyType
    00239                 );
    00240
    00241     ExFreePool(CmpCopyStack);
    00242     return result;
    00243 }

HCELL_INDEX CmpCopyValue | ( | PHHIVE | SourceHive,
|  | HCELL_INDEX | SourceValueCell,
|  | PHHIVE | TargetHive,
|  | HSTORAGE_TYPE | Type
| ) |

Definition at line 895 of file cmtrecpy.c.

References CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CML_MINOR, CMLOG, CmpCopyCell(), CmpIsHKeyValueSmall, CMS_SAVRES, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, HCELL_INDEX, HCELL_NIL, HvFreeCell(), HvGetCell, _CELL_DATA::_u::KeyValue, and _CELL_DATA::u.

Referenced by CmpCopyKeyPartial(), CmpMergeKeyValues(), and CmpSyncKeyValues().

    00903                    :
    00904
    00905     Copy a value entry.  Copies the body of a value entry and the
    00906     data.  Returns cell of new value entry.
    00907
    00908 Arguments:
    00909
    00910     SourceHive - pointer to hive control structure for source
    00911
    00912     SourceValueCell - value entry being copied
    00913
    00914     TargetHive - pointer to hive control structure for target
    00915
    00916     Type - storage type to allocate for target (stable or volatile)
    00917
    00918 Return Value:
    00919
    00920     HCELL_INDEX - Cell of body of new value entry, or HCELL_NIL
    00921         if some error.
    00922
    00923 --*/
    00924 {
    00925     HCELL_INDEX newvalue;
    00926     HCELL_INDEX newdata;
    00927     PCELL_DATA pvalue;
    00928     ULONG       datalength;
    00929     HCELL_INDEX olddata;
    00930     ULONG       tempdata;
    00931     BOOLEAN     small;
    00932
    00933     CMLOG(CML_MINOR, CMS_SAVRES) {
    00934         KdPrint(("CmpCopyValue:\n"));
    00935         KdPrint(("\tSHive=%08lx SCell=%08lx\n",SourceHive,SourceValueCell));
    00936         KdPrint(("\tTargetHive=%08lx\n",TargetHive));
    00937     }
    00938
    00939     //
    00940     // get source data
    00941     //
    00942     pvalue = HvGetCell(SourceHive, SourceValueCell);
    00943     small = CmpIsHKeyValueSmall(datalength, pvalue->u.KeyValue.DataLength);
    00944     olddata = pvalue->u.KeyValue.Data;
    00945
    00946     //
    00947     // Copy body
    00948     //
    00949     newvalue = CmpCopyCell(SourceHive, SourceValueCell, TargetHive, Type);
    00950     if (newvalue == HCELL_NIL) {
    00951         return HCELL_NIL;
    00952     }
    00953
    00954     //
    00955     // Copy data (if any)
    00956     //
    00957     if (datalength > 0) {
    00958
    00959         if (datalength > CM_KEY_VALUE_SMALL) {
    00960
    00961             //
    00962             // there's data, and it's "big", so do standard copy
    00963             //
    00964             newdata = CmpCopyCell(SourceHive, olddata, TargetHive, Type);
    00965
    00966             if (newdata == HCELL_NIL) {
    00967                 HvFreeCell(TargetHive, newvalue);
    00968                 return HCELL_NIL;
    00969             }
    00970
    00971             pvalue = HvGetCell(TargetHive, newvalue);
    00972             pvalue->u.KeyValue.Data = newdata;
    00973             pvalue->u.KeyValue.DataLength = datalength;
    00974
    00975         } else {
    00976
    00977             //
    00978             // the data is small, but may be stored in either large or
    00979             // small format for historical reasons
    00980             //
    00981             if (small) {
    00982
    00983                 //
    00984                 // data is already small, so just do a body to body copy
    00985                 //
    00986                 tempdata = pvalue->u.KeyValue.Data;
    00987
    00988             } else {
    00989
    00990                 //
    00991                 // data is stored externally in old cell, will be internal in new
    00992                 //
    00993                 pvalue = HvGetCell(SourceHive, pvalue->u.KeyValue.Data);
    00994                 tempdata = *((PULONG)pvalue);
    00995             }
    00996             pvalue = HvGetCell(TargetHive, newvalue);
    00997             pvalue->u.KeyValue.Data = tempdata;
    00998             pvalue->u.KeyValue.DataLength =
    00999                 datalength + CM_KEY_VALUE_SPECIAL_SIZE;
    01000
    01001         }
    01002     }
    01003
    01004     return newvalue;
    01005 }

NTSTATUS CmpCreateEvent | ( | IN EVENT_TYPE | eventType,
|  | OUT PHANDLE | eventHandle,
|  | OUT PKEVENT * | event
| ) |

Definition at line 313 of file cmwrapr.c.

References FALSE, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, and ObReferenceObjectByHandle().

Referenced by CmpFileRead(), CmpFileWrite(), and CmpOpenHiveFiles().

    00318 {
    00319     NTSTATUS status;
    00320     OBJECT_ATTRIBUTES obja;
    00321
    00322     InitializeObjectAttributes( &obja, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL );
    00323     status = ZwCreateEvent(
    00324         eventHandle,
    00325         EVENT_ALL_ACCESS,
    00326         &obja,
    00327         eventType,
    00328         FALSE);
    00329
    00330     if (!NT_SUCCESS(status)) {
    00331         return status;
    00332     }
    00333
    00334     status = ObReferenceObjectByHandle(
    00335         *eventHandle,
    00336         EVENT_ALL_ACCESS,
    00337         NULL,
    00338         KernelMode,
    00339         event,
    00340         NULL);
    00341
    00342     if (!NT_SUCCESS(status)) {
    00343         ZwClose(*eventHandle);
    00344         return status;
    00345     }
    00346     return status;
    00347 }

NTSTATUS CmpCreateHwProfileFriendlyName | ( | IN HANDLE | IDConfigDB,
|  | IN ULONG | DockingState,
|  | IN ULONG | NewProfileNumber,
|  | OUT PUNICODE_STRING | FriendlyName
| ) |

Definition at line 2529 of file hwprofil.c.

References CM_HARDWARE_PROFILE_STR_DOCKED, CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES, CM_HARDWARE_PROFILE_STR_UNDOCKED, CM_HARDWARE_PROFILE_STR_UNKNOWN, HW_PROFILE_DOCKSTATE_DOCKED, HW_PROFILE_DOCKSTATE_UNDOCKED, HW_PROFILE_DOCKSTATE_UNKNOWN, KeLoaderBlock, L, _LOADER_PARAMETER_BLOCK::LoadOrderListHead, MAX_FRIENDLY_NAME_LENGTH, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PsLoadedModuleList, RtlAnsiStringToUnicodeString(), RtlCreateUnicodeString(), RtlFindMessage(), RtlFreeUnicodeString(), RtlInitAnsiString(), RtlInitUnicodeString(), and TRUE.

Referenced by CmpCloneHwProfile().

    02537                    :
    02538
    02539     Create a new FriendlyName for a new Hardware Profile, given the DockState.
    02540     If a new profile name based on the DockState cannot be created, an attempt
    02541     is made to create a default FriendlyName based on NewProfileNumber.  If
    02542     successful, a unicode string with the new profile friendlyName is created.
    02543     It is the responsibility of the caller to free this using
    02544     RtlFreeUnicodeString.  If unsuccesful, no string is returned.
    02545
    02546 Arguments:
    02547
    02548     IDConfigDB:       Handle to the IDConfigDB registry key.
    02549
    02550     DockingState:     The Docking State of the profile for which the new
    02551                       FriendlyName is being created.  This should be one of:
    02552                       HW_PROFILE_DOCKSTATE_DOCKED,
    02553                       HW_PROFILE_DOCKSTATE_UNDOCKED, or
    02554                       HW_PROFILE_DOCKSTATE_UNKNOWN
    02555
    02556     NewProfileNumber: The number of the new profile being created.  If unable to
    02557                       create a DockState specific FriendlyName, this value will
    02558                       be used to create a (not-so) FriendlyName.
    02559
    02560     FriendlyName:     Supplies a unicode string to receive the FriendlyName for this
    02561                       new profile.  The caller is expected to free this with
    02562                       RtlFreeUnicodeString.
    02563
    02564 Return:
    02565
    02566     NTSTATUS code.    Currently returns STATUS_SUCCESS, or STATUS_UNSUCCESSFUL.
    02567
    02568 Notes:
    02569
    02570     The new FriendlyName is generated from the DockState and appropriate
    02571     counter, and may not necessarily be unique among the existing Hardware
    02572     Profiles.
    02573
    02574     The naming scheme used here (including the localized strings in the kernel
    02575     message table) should be kept in sync with that provided to the user through
    02576     the Hardware Profile control panel applet.
    02577
    02578 --*/
    02579 {
    02580     NTSTATUS status = STATUS_SUCCESS;
    02581     ANSI_STRING       ansiString;
    02582     UNICODE_STRING    unicodeString;
    02583     UNICODE_STRING    labelName, keyName;
    02584     PMESSAGE_RESOURCE_ENTRY messageEntry;
    02585     PLDR_DATA_TABLE_ENTRY dataTableEntry;
    02586     ULONG             messageId;
    02587     UCHAR             valueBuffer[256];
    02588     WCHAR             friendlyNameBuffer[MAX_FRIENDLY_NAME_LENGTH/sizeof(WCHAR)];
    02589     PKEY_VALUE_FULL_INFORMATION  keyValueInfo;
    02590     ULONG             length, index;
    02591     HANDLE            hardwareProfiles=NULL;
    02592     OBJECT_ATTRIBUTES attributes;
    02593
    02594     PAGED_CODE ();
    02595
    02596     //
    02597     // Make sure we were given a place to put the FriendlyName
    02598     //
    02599     if (!FriendlyName) {
    02600         return STATUS_INVALID_PARAMETER;
    02601     }
    02602
    02603     //
    02604     // If we don't have a handle to IDConfigDB, try to assign a default
    02605     // FriendlyName on the way out.
    02606     //
    02607     if (!IDConfigDB) {
    02608         status = STATUS_INVALID_PARAMETER;
    02609         goto Exit;
    02610     }
    02611
    02612     //
    02613     // Determine the appropriate message to use, based on the DockState.
    02614     //
    02615     if ((DockingState & HW_PROFILE_DOCKSTATE_UNKNOWN) == HW_PROFILE_DOCKSTATE_UNKNOWN){
    02616         messageId = HARDWARE_PROFILE_UNKNOWN_STRING;
    02617         RtlInitUnicodeString(&labelName, CM_HARDWARE_PROFILE_STR_UNKNOWN);
    02618     } else if (DockingState & HW_PROFILE_DOCKSTATE_DOCKED) {
    02619         messageId = HARDWARE_PROFILE_DOCKED_STRING;
    02620         RtlInitUnicodeString(&labelName, CM_HARDWARE_PROFILE_STR_DOCKED);
    02621     } else if (DockingState & HW_PROFILE_DOCKSTATE_UNDOCKED) {
    02622         messageId = HARDWARE_PROFILE_UNDOCKED_STRING;
    02623         RtlInitUnicodeString(&labelName, CM_HARDWARE_PROFILE_STR_UNDOCKED);
    02624     } else {
    02625         messageId = HARDWARE_PROFILE_UNKNOWN_STRING;
    02626         RtlInitUnicodeString(&labelName, CM_HARDWARE_PROFILE_STR_UNKNOWN);
    02627     }
    02628
    02629     //
    02630     // Find the message entry in the kernel's own message table.  KeLoaderBlock
    02631     // is available when we're creating hardware profiles during system
    02632     // initialization only; for profiles created thereafter, use the the first
    02633     // entry of the PsLoadedModuleList to get the image base of the kernel.
    02634     //
    02635     if (KeLoaderBlock) {
    02636         dataTableEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
    02637                                            LDR_DATA_TABLE_ENTRY,
    02638                                            InLoadOrderLinks);
    02639     } else if (PsLoadedModuleList.Flink) {
    02640         dataTableEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink,
    02641                                            LDR_DATA_TABLE_ENTRY,
    02642                                            InLoadOrderLinks);
    02643     } else {
    02644         status = STATUS_UNSUCCESSFUL;
    02645         goto Exit;
    02646     }
    02647
    02648     status = RtlFindMessage(dataTableEntry->DllBase,
    02649                             (ULONG_PTR)11, // RT_MESSAGETABLE
    02650                             MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), // System default language
    02651                             messageId,
    02652                             &messageEntry);
    02653
    02654     if (!NT_SUCCESS(status)) {
    02655         goto Exit;
    02656     }
    02657
    02658     if(!(messageEntry->Flags & MESSAGE_RESOURCE_UNICODE)) {
    02659         //
    02660         // If the message is not unicode, convert to unicode.
    02661         // Let the conversion routine allocate the buffer.
    02662         //
    02663         RtlInitAnsiString(&ansiString,messageEntry->Text);
    02664         status = RtlAnsiStringToUnicodeString(&unicodeString,&ansiString,TRUE);
    02665     } else {
    02666         //
    02667         // Message is already unicode. Make a copy.
    02668         //
    02669         status = RtlCreateUnicodeString(&unicodeString,(PWSTR)messageEntry->Text);
    02670     }
    02671
    02672     if(!NT_SUCCESS(status)) {
    02673         goto Exit;
    02674     }
    02675
    02676     //
    02677     // Strip the trailing CRLF.
    02678     //
    02679     if (unicodeString.Length  > 2 * sizeof(WCHAR)) {
    02680         unicodeString.Length -= 2 * sizeof(WCHAR);
    02681         unicodeString.Buffer[unicodeString.Length / sizeof(WCHAR)] = UNICODE_NULL;
    02682     }
    02683
    02684     //
    02685     // Check that the size of the label, with any numeric tag that may
    02686     // potentially be added (up to 4 digits, preceded by a space) is not too
    02687     // big.
    02688     //
    02689     if ((unicodeString.Length + 5*sizeof(WCHAR) + sizeof(UNICODE_NULL)) >
    02690         MAX_FRIENDLY_NAME_LENGTH) {
    02691         status = STATUS_UNSUCCESSFUL;
    02692         goto Clean;
    02693     }
    02694
    02695     //
    02696     // Open the Hardware Profiles key.
    02697     //
    02698     RtlInitUnicodeString(&keyName, CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES);
    02699     InitializeObjectAttributes(&attributes,
    02700                                &keyName,
    02701                                OBJ_CASE_INSENSITIVE,
    02702                                IDConfigDB,
    02703                                NULL);
    02704     status = ZwOpenKey(&hardwareProfiles,
    02705                        KEY_READ,
    02706                        &attributes);
    02707     if (!NT_SUCCESS(status)) {
    02708         hardwareProfiles = NULL;
    02709         goto Clean;
    02710     }
    02711
    02712     //
    02713     // Retrieve the counter of FriendlyNames we have previously assigned, based
    02714     // on this DockState.
    02715     //
    02716     keyValueInfo = (PKEY_VALUE_FULL_INFORMATION) valueBuffer;
    02717     status = ZwQueryValueKey(hardwareProfiles,
    02718                              &labelName,
    02719                              KeyValueFullInformation,
    02720                              valueBuffer,
    02721                              sizeof(valueBuffer),
    02722                              &length);
    02723
    02724     if (NT_SUCCESS(status) && (keyValueInfo->Type == REG_DWORD)) {
    02725         //
    02726         // Increment the counter.
    02727         //
    02728         index = (* (PULONG) ((PUCHAR)keyValueInfo + keyValueInfo->DataOffset));
    02729         index++;
    02730     } else {
    02731         //
    02732         // Missing or invalid counter value; start the counter at "1".
    02733         //
    02734         index = 1;
    02735     }
    02736
    02737     //
    02738     // Update the counter in the registry.
    02739     //
    02740     status = ZwSetValueKey(hardwareProfiles,
    02741                            &labelName,
    02742                            0,
    02743                            REG_DWORD,
    02744                            &index,
    02745                            sizeof(index));
    02746     if (!NT_SUCCESS(status)) {
    02747         goto Clean;
    02748     }
    02749
    02750     //
    02751     // Copy the FriendlyName, adding the index if necessary.
    02752     //
    02753     if ((messageId == HARDWARE_PROFILE_UNKNOWN_STRING) || (index > 1)) {
    02754         swprintf(friendlyNameBuffer, L"%s %u",
    02755                  unicodeString.Buffer, index);
    02756     } else {
    02757         wcscpy(friendlyNameBuffer, unicodeString.Buffer);
    02758     }
    02759
    02760  Clean:
    02761
    02762     RtlFreeUnicodeString(&unicodeString);
    02763
    02764     if (hardwareProfiles!=NULL) {
    02765         ZwClose(hardwareProfiles);
    02766     }
    02767
    02768  Exit:
    02769
    02770     if (!NT_SUCCESS(status)) {
    02771         //
    02772         // If we failed to assign a counter-based FriendlyName for whatever
    02773         // reason, give the new profile a new (not so) friendly name as a last
    02774         // resort.
    02775         //
    02776         swprintf (friendlyNameBuffer, L"%04d", NewProfileNumber);
    02777         status = STATUS_SUCCESS;
    02778     }
    02779
    02780     //
    02781     // Create the unicode string to return to the caller.
    02782     //
    02783     if (!RtlCreateUnicodeString(FriendlyName, (PWSTR)friendlyNameBuffer)) {
    02784         status = STATUS_UNSUCCESSFUL;
    02785     }
    02786
    02787     return status;
    02788
    02789 } // CmpCreateHwProfileFriendlyName
    } // CmpCreateHwProfileFriendlyName

PCM_KEY_CONTROL_BLOCK CmpCreateKeyControlBlock | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | PCM_KEY_NODE | Node,
|  | PCM_KEY_CONTROL_BLOCK | ParentKcb,
|  | BOOLEAN | FakeKey,
|  | PUNICODE_STRING | KeyName
| ) |

Definition at line 824 of file cmsubs.c.

References ASSERT, ASSERT_KCB, ASSERT_KEYBODY_LIST_EMPTY, Cell, CM_KCB_KEY_NON_EXIST, CmpDereferenceKeyControlBlockWithLock(), CmpGetNameControlBlock(), CmpInsertKeyHash(), CmpReferenceKeyControlBlock(), CmpRemoveFromDelayedClose(), CmpRemoveKeyControlBlock(), _CM_KEY_CONTROL_BLOCK::ConvKey, _CHILD_LIST::Count, _CM_KEY_CONTROL_BLOCK::Delete, ExAllocatePoolWithTag, ExFreePoolWithTag, FALSE, _CM_KEY_NODE::Flags, Hive, INIT_KCB_KEYBODY_LIST, kcb(), KeyName, _CHILD_LIST::List, LOCK_KCB_TREE, NULL, PagedPool, PROTECTED_POOL, RtlUpcaseUnicodeChar(), _CM_KEY_NODE::Security, SET_KCB_SIGNATURE, Size, _CM_KEY_CONTROL_BLOCK::TotalLevels, UNLOCK_KCB_TREE, USHORT, and _CM_KEY_NODE::ValueList.

Referenced by CmpAddInfoAfterParseFailure(), CmpCreateRegistryRoot(), CmpDoCreateChild(), CmpDoOpen(), and CmpParseKey().

    00834                    :
    00835
    00836     Allocate and initialize a key control block, insert it into
    00837     the kcb tree.
    00838
    00839     Full path will be BaseName + '\' + KeyName, unless BaseName
    00840     NULL, in which case the full path is simply KeyName.
    00841
    00842     RefCount of returned KCB WILL have been incremented to reflect
    00843     callers ref.
    00844
    00845 Arguments:
    00846
    00847     Hive - Supplies Hive that holds the key we are creating a KCB for.
    00848
    00849     Cell - Supplies Cell that contains the key we are creating a KCB for.
    00850
    00851     Node - Supplies pointer to key node.
    00852
    00853     ParentKcb - Parent kcb of the kcb to be created
    00854
    00855     FakeKey - Whether the kcb to be create is a fake one or not
    00856
    00857     KeyName - the subkey name to of the KCB to be created.
    00858
    00859     NOTE:  We need the parameter instead of just using the name in the KEY_NODE
    00860            because there is no name in the root cell of a hive.
    00861
    00862 Return Value:
    00863
    00864     NULL - failure (insufficient memory)
    00865     else a pointer to the new kcb.
    00866
    00867 --*/
    00868 {
    00869     PCM_KEY_CONTROL_BLOCK   kcb;
    00870     PCM_KEY_CONTROL_BLOCK   kcbmatch=NULL;
    00871     PCMHIVE CmHive;
    00872     ULONG namelength;
    00873     PUNICODE_STRING         fullname;
    00874     ULONG       Size;
    00875     ULONG i;
    00876
    00877     UNICODE_STRING         NodeName;
    00878     ULONG ConvKey=0;
    00879     ULONG Cnt;
    00880     WCHAR *Cp;
    00881
    00882     //
    00883     // ParentKCb has the base hash value.
    00884     //
    00885     if (ParentKcb) {
    00886         ConvKey = ParentKcb->ConvKey;
    00887     }
    00888
    00889     NodeName = *KeyName;
    00890
    00891     while ((NodeName.Length > 0) && (NodeName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) {
    00892         //
    00893         // This must be the \REGISTRY.
    00894         // Strip off the leading OBJ_NAME_PATH_SEPARATOR
    00895         //
    00896         NodeName.Buffer++;
    00897         NodeName.Length -= sizeof(WCHAR);
    00898     }
    00899
    00900     //
    00901     // Manually compute the hash to use.
    00902     //
    00903     ASSERT(NodeName.Length > 0);
    00904
    00905     if (NodeName.Length) {
    00906         Cp = NodeName.Buffer;
    00907         for (Cnt=0; Cnt<NodeName.Length; Cnt += sizeof(WCHAR)) {
    00908             if ((*Cp != OBJ_NAME_PATH_SEPARATOR) &&
    00909                 (*Cp != UNICODE_NULL)) {
    00910                 ConvKey = 37 * ConvKey + (ULONG)RtlUpcaseUnicodeChar(*Cp);
    00911             }
    00912             ++Cp;
    00913         }
    00914     }
    00915
    00916     //
    00917     // Create a new kcb, which we will free if one already exists
    00918     // for this key.
    00919     // Now it is a fixed size structure.
    00920     //
    00921     kcb = ExAllocatePoolWithTag(PagedPool,
    00922                                 sizeof(CM_KEY_CONTROL_BLOCK),
    00923                                 CM_KCB_TAG | PROTECTED_POOL);
    00924
    00925
    00926     if (kcb == NULL) {
    00927         return(NULL);
    00928     } else {
    00929         SET_KCB_SIGNATURE(kcb, KCB_SIGNATURE);
    00930         INIT_KCB_KEYBODY_LIST(kcb);
    00931         kcb->Delete = FALSE;
    00932         kcb->RefCount = 1;
    00933         kcb->KeyHive = Hive;
    00934         kcb->KeyCell = Cell;
    00935         kcb->KeyNode = Node;
    00936         kcb->ConvKey = ConvKey;
    00937
    00938     }
    00939
    00940     ASSERT_KCB(kcb);
    00941     //
    00942     // Find location to insert kcb in kcb tree.
    00943     //
    00944
    00945
    00946     LOCK_KCB_TREE();
    00947
    00948     //
    00949     // Add the KCB to the hash table
    00950     //
    00951     kcbmatch = CmpInsertKeyHash(&kcb->KeyHash, FakeKey);
    00952     if (kcbmatch != NULL) {
    00953         //
    00954         // A match was found.
    00955         //
    00956         ASSERT(!kcbmatch->Delete);
    00957         SET_KCB_SIGNATURE(kcb, '1FmC');
    00958         ASSERT_KEYBODY_LIST_EMPTY(kcb);
    00959         ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    00960         ASSERT_KCB(kcbmatch);
    00961         kcb = kcbmatch;
    00962         if (kcb->RefCount == 0) {
    00963             //
    00964             // This kcb is on the delayed close list. Remove it from that
    00965             // list.
    00966             //
    00967             CmpRemoveFromDelayedClose(kcb);
    00968         }
    00969         if ((USHORT)(kcb->RefCount + 1) == 0) {
    00970             //
    00971             // We have maxed out the ref count on this key. Probably
    00972             // some bogus app has opened the same key 64K times without
    00973             // ever closing it. Just fail the open, they've got enough
    00974             // handles already.
    00975             //
    00976             ASSERT(kcb->RefCount + 1 != 0);
    00977             kcb = NULL;
    00978         } else {
    00979             ++kcb->RefCount;
    00980         }
    00981     }
    00982     else {
    00983         //
    00984         // No kcb created previously, fill in all the data.
    00985         //
    00986
    00987         //
    00988         // Now try to reference the parentkcb
    00989         //
    00990
    00991         if (ParentKcb) {
    00992             if (CmpReferenceKeyControlBlock(ParentKcb)) {
    00993                 kcb->ParentKcb = ParentKcb;
    00994                 kcb->TotalLevels = ParentKcb->TotalLevels + 1;
    00995             } else {
    00996                 //
    00997                 // We have maxed out the ref count on the parent.
    00998                 // Since it has been cached in the cachetable,
    00999                 // remove it first before we free the allocation.
    01000                 //
    01001                 CmpRemoveKeyControlBlock(kcb);
    01002                 SET_KCB_SIGNATURE(kcb, '2FmC');
    01003                 ASSERT_KEYBODY_LIST_EMPTY(kcb);
    01004                 ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    01005                 kcb = NULL;
    01006             }
    01007         } else {
    01008             //
    01009             // It is the \REGISTRY node.
    01010             //
    01011             kcb->ParentKcb = NULL;
    01012             kcb->TotalLevels = 1;
    01013         }
    01014
    01015         if (kcb) {
    01016             //
    01017             // Now try to find the Name Control block that has the name for this node.
    01018             //
    01019
    01020             kcb->NameBlock = CmpGetNameControlBlock (&NodeName);
    01021
    01022             if (kcb->NameBlock) {
    01023                 //
    01024                 // Now fill in all the data needed for the cache.
    01025                 //
    01026                 kcb->ValueCache.Count = Node->ValueList.Count;
    01027                 kcb->ValueCache.ValueList = (ULONG_PTR) Node->ValueList.List;
    01028
    01029                 kcb->Flags = Node->Flags;
    01030                 kcb->ExtFlags = 0;
    01031                 kcb->DelayedCloseIndex = 0;
    01032
    01033                 //
    01034                 // Cache the security cells in the kcb
    01035                 //
    01036                 kcb->Security = Node->Security;
    01037
    01038                 if (FakeKey) {
    01039                     //
    01040                     // The KCb to be created is a fake one
    01041                     //
    01042                     kcb->ExtFlags |= CM_KCB_KEY_NON_EXIST;
    01043                 }
    01044             } else {
    01045                 //
    01046                 // We have maxed out the ref count on the Name.
    01047                 //
    01048
    01049                 //
    01050                 // First dereference the parent KCB.
    01051                 //
    01052                 CmpDereferenceKeyControlBlockWithLock(ParentKcb);
    01053
    01054                 CmpRemoveKeyControlBlock(kcb);
    01055                 SET_KCB_SIGNATURE(kcb, '3FmC');
    01056                 ASSERT_KEYBODY_LIST_EMPTY(kcb);
    01057                 ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
    01058                 kcb = NULL;
    01059             }
    01060         }
    01061     }
    01062
    01063
    01064     UNLOCK_KCB_TREE();
    01065     return kcb;
    01066 }

NTSTATUS CmpDeleteChildByName | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | UNICODE_STRING | Name,
|  | PHCELL_INDEX | ChildCell
| ) |

VOID CmpDeleteKeyObject | ( | IN PVOID | Object | ) |

Definition at line 31 of file cmdelete.c.

References ASSERT, CML_MAJOR, CMLOG, CmpDereferenceKeyControlBlock(), CmpFlushNotify(), CmpLockRegistry(), CmpUnlockRegistry(), CMS_NTAPI, DELIST_KEYBODY_FROM_KEYBODY_LIST, _CM_KEY_CONTROL_BLOCK::Flags, KEY_BODY_TYPE, KEY_PREDEF_HANDLE, _CM_KEY_BODY::KeyControlBlock, NULL, PAGED_CODE, REG_PREDEF_HANDLE_MASK, and _CM_KEY_BODY::Type.

Referenced by CmpCreateObjectTypes().

    00036                    :
    00037
    00038     This routine interfaces to the NT Object Manager.  It is invoked when
    00039     the last reference to a particular Key object (or Key Root object)
    00040     is destroyed.
    00041
    00042     If the Key object going away holds the last reference to
    00043     the extension it is associated with, that extension is destroyed.
    00044
    00045 Arguments:
    00046
    00047     Object - supplies a pointer to a KeyRoot or Key, thus -> KEY_BODY.
    00048
    00049 Return Value:
    00050
    00051     NONE.
    00052
    00053 --*/
    00054 {
    00055     PCM_KEY_CONTROL_BLOCK   KeyControlBlock;
    00056     PCM_KEY_BODY            KeyBody;
    00057
    00058     PAGED_CODE();
    00059
    00060     CMLOG(CML_MAJOR, CMS_NTAPI) {
    00061         KdPrint(("CmpDeleteKeyObject: Object = %08lx\n", Object));
    00062     }
    00063
    00064     CmpLockRegistry();
    00065
    00066     KeyBody = (PCM_KEY_BODY)Object;
    00067
    00068     if (KeyBody->Type==KEY_BODY_TYPE) {
    00069         KeyControlBlock = KeyBody->KeyControlBlock;
    00070
    00071         //
    00072         // the keybody should be initialized; when kcb is null, something went wrong
    00073         // between the creation and the dereferenciation of the object
    00074         //
    00075         if( KeyControlBlock != NULL ) {
    00076
    00077             //
    00078             // Clean up any outstanding notifies attached to the KeyBody
    00079             //
    00080             CmpFlushNotify(KeyBody);
    00081
    00082             //
    00083             // Remove our reference to the KeyControlBlock, clean it up, perform any
    00084             // pend-till-final-close operations.
    00085             //
    00086             // NOTE: Delete notification is seen at the parent of the deleted key,
    00087             //       not the deleted key itself.  If any notify was outstanding on
    00088             //       this key, it was cleared away above us.  Only parent/ancestor
    00089             //       keys will see the report.
    00090             //
    00091             //
    00092             // The dereference will free the KeyControlBlock.  If the key was deleted, it
    00093             // has already been removed from the hash table, and relevent notifications
    00094             // posted then as well.  All we are doing is freeing the tombstone.
    00095             //
    00096             // If it was not deleted, we're both cutting the kcb out of
    00097             // the kcb list/tree, AND freeing its storage.
    00098             //
    00099
    00100             DELIST_KEYBODY_FROM_KEYBODY_LIST(KeyBody);
    00101             CmpDereferenceKeyControlBlock(KeyControlBlock);
    00102         }
    00103     } else {
    00104         //
    00105         // This must be a predefined handle
    00106         //  some sanity asserts
    00107         //
    00108         KeyControlBlock = KeyBody->KeyControlBlock;
    00109
    00110         ASSERT( KeyBody->Type&REG_PREDEF_HANDLE_MASK);
    00111         ASSERT( KeyControlBlock->Flags&KEY_PREDEF_HANDLE );
    00112
    00113         if( KeyControlBlock != NULL ) {
    00114             CmpDereferenceKeyControlBlock(KeyControlBlock);
    00115         }
    00116
    00117     }
    00118     CmpUnlockRegistry();
    00119     return;
    00120 }

VOID CmpDeleteTree | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 34 of file cmtredel.c.

References Cell, CML_MAJOR, CMLOG, CmpFindSubKeyByNumber(), CmpFreeKeyByCell(), CMS_SAVRES, HCELL_INDEX, Hive, HvGetCell, _CM_KEY_NODE::Parent, Stable, _CM_KEY_NODE::SubKeyCounts, TRUE, and Volatile.

Referenced by CmpSyncSubKeysAfterDelete(), and CmRestoreKey().

    00040                    :
    00041
    00042     Delete all child subkeys, recursively, of Hive.Cell.  Delete all
    00043     value entries of Hive.Cell.  Do NOT delete Hive.Cell itself.
    00044
    00045     NOTE:   If this call fails part way through, it will NOT undo
    00046             any successfully completed deletes.
    00047
    00048     NOTE:   This algorithm can deal with a hive of any depth, at the
    00049             cost of some "redundent" scaning and mapping.
    00050
    00051 Arguments:
    00052
    00053     Hive - pointer to hive control structure for hive to delete from
    00054
    00055     Cell - index of cell at root of tree to delete
    00056
    00057 Return Value:
    00058
    00059     BOOLEAN - Result code from call, among the following:
    00060         TRUE - it worked
    00061         FALSE - the tree delete was not completed (though more than 0
    00062                 keys may have been deleted)
    00063
    00064 --*/
    00065 {
    00066     ULONG  count;
    00067     HCELL_INDEX ptr1;
    00068     HCELL_INDEX ptr2;
    00069     HCELL_INDEX parent;
    00070     PCM_KEY_NODE Node;
    00071
    00072     CMLOG(CML_MAJOR, CMS_SAVRES) {
    00073         KdPrint(("CmpDeleteTree:\n"));
    00074         KdPrint(("\tHive=%08lx Cell=%08lx\n",Hive,Cell));
    00075     }
    00076
    00077     ptr1 = Cell;
    00078
    00079     while(TRUE) {
    00080
    00081         Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr1);
    00082         count = Node->SubKeyCounts[Stable] +
    00083                 Node->SubKeyCounts[Volatile];
    00084         parent = Node->Parent;
    00085
    00086         if (count > 0) {                // ptr1->count > 0?
    00087
    00088             //
    00089             // subkeys exist, find and delete them
    00090             //
    00091             ptr2 = CmpFindSubKeyByNumber(Hive, Node, 0);
    00092
    00093             Node = (PCM_KEY_NODE)HvGetCell(Hive, ptr2);
    00094             count = Node->SubKeyCounts[Stable] +
    00095                     Node->SubKeyCounts[Volatile];
    00096
    00097             if (count > 0) {            // ptr2->count > 0?
    00098
    00099                 //
    00100                 // subkey has subkeys, descend to next level
    00101                 //
    00102                 ptr1 = ptr2;
    00103                 continue;
    00104
    00105             } else {
    00106
    00107                 //
    00108                 // have found leaf, delete it
    00109                 //
    00110                 CmpFreeKeyByCell(Hive, ptr2, TRUE);
    00111                 continue;
    00112             }
    00113
    00114         } else {
    00115
    00116             //
    00117             // no more subkeys at this level, we are now a leaf.
    00118             //
    00119             if (ptr1 != Cell) {
    00120
    00121                 //
    00122                 // we are not at the root cell, so ascend to parent
    00123                 //
    00124                 ptr1 = parent;          // ptr1 = ptr1->parent
    00125                 continue;
    00126
    00127             } else {
    00128
    00129                 //
    00130                 // we are at the root cell, we are done
    00131                 //
    00132                 return;
    00133             }
    00134         } // outer if
    00135     } // while
    00136 }

VOID CmpDereferenceKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1153 of file cmsubs.c.

References CmpDereferenceKeyControlBlockWithLock(), LOCK_KCB_TREE, and UNLOCK_KCB_TREE.

Referenced by CmpAddInfoAfterParseFailure(), CmpDeleteKeyObject(), CmpDoOpen(), and CmpParseKey().

    01158                    :
    01159
    01160     Decrements the reference count on a key control block, and frees it if it
    01161     becomes zero.
    01162
    01163     It is expected that no notify control blocks remain if the reference count
    01164     becomes zero.
    01165
    01166 Arguments:
    01167
    01168     KeyControlBlock - pointer to a key control block.
    01169
    01170 Return Value:
    01171
    01172     NONE.
    01173
    01174 --*/
    01175 {
    01176     LOCK_KCB_TREE();
    01177     CmpDereferenceKeyControlBlockWithLock(KeyControlBlock) ;
    01178     UNLOCK_KCB_TREE();
    01179     return;
    01180 }

VOID CmpDereferenceKeyControlBlockWithLock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1184 of file cmsubs.c.

References ASSERT, ASSERT_KCB, CM_KCB_NO_DELAY_CLOSE, CmpCleanUpKcbCacheWithLock(), CmpDelayedCloseCurrent, CmpDelayedCloseSize, CmpDelayedCloseTable, CmpDelayedFreeIndex, _CM_KEY_CONTROL_BLOCK::DelayedCloseIndex, _CM_KEY_CONTROL_BLOCK::Delete, _CM_KEY_CONTROL_BLOCK::ExtFlags, NULL, _CM_KEY_CONTROL_BLOCK::RefCount, and USHORT.

Referenced by CmEnumerateValueKey(), CmpCleanUpKcbValueCache(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlock(), CmpDoCreateChild(), CmpParseKey(), and CmQueryValueKey().

    01187 {
    01188     ULONG_PTR FreeIndex;
    01189     PCM_KEY_CONTROL_BLOCK KcbToFree;
    01190
    01191
    01192
    01193     ASSERT_KCB(KeyControlBlock);
    01194
    01195     if (--KeyControlBlock->RefCount == 0) {
    01196         //
    01197         // Remove kcb from the tree
    01198         //
    01199         if (KeyControlBlock->ExtFlags & CM_KCB_NO_DELAY_CLOSE) {
    01200             //
    01201             // Free storage directly so we can clean up junk quickly.
    01202             //
    01203             //
    01204             // Need to free all cached Index List, Index Leaf, Value, etc.
    01205             //
    01206             CmpCleanUpKcbCacheWithLock(KeyControlBlock);
    01207         } else if (!KeyControlBlock->Delete) {
    01208
    01209             //
    01210             // Put this kcb on our delayed close list.
    01211             //
    01212             // First check the free list for a free slot.
    01213             //
    01214             FreeIndex = CmpDelayedFreeIndex;
    01215             if (FreeIndex != -1) {
    01216                 ASSERT(FreeIndex < CmpDelayedCloseSize);
    01217                 CmpDelayedFreeIndex = (ULONG_PTR)CmpDelayedCloseTable[FreeIndex];
    01218                 KeyControlBlock->DelayedCloseIndex = (USHORT) FreeIndex;
    01219                 ASSERT((CmpDelayedFreeIndex == -1) ||
    01220                        (CmpDelayedFreeIndex < CmpDelayedCloseSize));
    01221                 CmpDelayedCloseTable[FreeIndex] = KeyControlBlock;
    01222             } else {
    01223
    01224                 //
    01225                 // Nothing is free, we have to get rid of something.
    01226                 //
    01227                 ASSERT(*CmpDelayedCloseCurrent != NULL);
    01228                 ASSERT(!(*CmpDelayedCloseCurrent)->Delete);
    01229                 //
    01230                 // Need to free all cached Index List, Index Leaf, Value, etc.
    01231                 // Change the code sequence for the recurrsive call to dereference the parent.
    01232                 //
    01233                 KcbToFree = *CmpDelayedCloseCurrent;
    01234                 *CmpDelayedCloseCurrent = KeyControlBlock;
    01235                 KeyControlBlock->DelayedCloseIndex = (USHORT)(CmpDelayedCloseCurrent - CmpDelayedCloseTable);
    01236                 ++CmpDelayedCloseCurrent;
    01237                 if ((ULONG)(CmpDelayedCloseCurrent - CmpDelayedCloseTable) == CmpDelayedCloseSize) {
    01238                     CmpDelayedCloseCurrent = CmpDelayedCloseTable;
    01239                 }
    01240
    01241                 CmpCleanUpKcbCacheWithLock(KcbToFree);
    01242             }
    01243         } else {
    01244             //
    01245             // Free storage directly as there is no point in putting this on
    01246             // our delayed close list.
    01247             //
    01248             //
    01249             // Need to free all cached Index List, Index Leaf, Value, etc.
    01250             //
    01251             CmpCleanUpKcbCacheWithLock(KeyControlBlock);
    01252         }
    01253     }
    01254
    01255     return;
    01256 }

BOOLEAN CmpDestroyHive | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell
| ) |

Definition at line 667 of file cminit.c.

References ASSERT, Cell, CmpFreeKeyByCell(), CmpMasterHive, FALSE, HCELL_INDEX, Hive, HiveList, HvGetCell, _CELL_DATA::_u::KeyNode, NT_SUCCESS, NTSTATUS(), _CM_KEY_NODE::Parent, Status, TRUE, and _CELL_DATA::u.

Referenced by CmUnloadKey().

    00674                    :
    00675
    00676     This routine tears down a cmhive.
    00677
    00678 Arguments:
    00679
    00680     Hive - Supplies a pointer to the hive to be freed.
    00681
    00682     Cell - Supplies index of the hive's root cell.
    00683
    00684 Return Value:
    00685
    00686     TRUE if successful
    00687     FALSE if some failure occurred
    00688
    00689 --*/
    00690
    00691 {
    00692     PCELL_DATA CellData;
    00693     HCELL_INDEX LinkCell;
    00694     NTSTATUS Status;
    00695
    00696     //
    00697     // First find the link cell.
    00698     //
    00699     CellData = HvGetCell(Hive, Cell);
    00700     LinkCell = CellData->u.KeyNode.Parent;
    00701
    00702     //
    00703     // Now delete the link cell.
    00704     //
    00705     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00706     Status = CmpFreeKeyByCell((PHHIVE)CmpMasterHive, LinkCell, TRUE);
    00707
    00708     if (NT_SUCCESS(Status)) {
    00709         //
    00710         // Take the hive out of the hive list
    00711         //
    00712         RemoveEntryList(&( ((PCMHIVE)Hive)->HiveList));
    00713         return(TRUE);
    00714     } else {
    00715         return(FALSE);
    00716     }
    00717 }

NTSTATUS CmpDoCreate | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PACCESS_STATE | AccessState,
|  | IN PUNICODE_STRING | Name,
|  | IN KPROCESSOR_MODE | AccessMode,
|  | IN PCM_PARSE_CONTEXT | Context,
|  | IN PCM_KEY_CONTROL_BLOCK | ParentKcb,
|  | OUT PVOID * | Object
| ) |

Definition at line 33 of file cmparse2.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CML_FLOW, CMLOG, CmpAddSubKey(), CmpCheckCreateAccess(), CmpCleanUpSubKeyInfo(), CmpDoCreateChild(), CmpFreeKeyByCell(), CMS_PARSE, _CM_KEY_SECURITY::Descriptor, FALSE, _CM_KEY_NODE::Flags, _CM_KEY_CONTROL_BLOCK::Flags, HCELL_INDEX, Hive, HvGetCell, HvGetCellType, HvMarkCellDirty(), KEY_SYM_LINK, _CM_KEY_BODY::KeyControlBlock, _CELL_DATA::_u::KeyNode, _CELL_DATA::_u::KeySecurity, _CM_KEY_NODE::MaxClassLen, _CM_KEY_NODE::MaxNameLen, Name, NT_SUCCESS, NTSTATUS(), NULL, _CM_KEY_CONTROL_BLOCK::ParentKcb, _CM_KEY_NODE::Security, _CELL_DATA::u, and Volatile.

Referenced by CmpParseKey().

    00045                    :
    00046
    00047     Performs the first step in the creation of a registry key.  This
    00048     routine checks to make sure the caller has the proper access to
    00049     create a key here, and allocates space for the child in the parent
    00050     cell.  It then calls CmpDoCreateChild to initialize the key and
    00051     create the key object.
    00052
    00053     This two phase creation allows us to share the child creation code
    00054     with the creation of link nodes.
    00055
    00056 Arguments:
    00057
    00058     Hive - supplies a pointer to the hive control structure for the hive
    00059
    00060     Cell - supplies index of node to create child under.
    00061
    00062     AccessState - Running security access state information for operation.
    00063
    00064     Name - supplies pointer to a UNICODE string which is the name of
    00065             the child to be created.
    00066
    00067     AccessMode - Access mode of the original caller.
    00068
    00069     Context - pointer to CM_PARSE_CONTEXT structure passed through
    00070                 the object manager
    00071
    00072     BaseName - Name of object create is relative to
    00073
    00074     KeyName - Relative name (to BaseName)
    00075
    00076     Object - The address of a variable to receive the created key object, if
    00077              any.
    00078
    00079 Return Value:
    00080
    00081     NTSTATUS
    00082
    00083 --*/
    00084 {
    00085     NTSTATUS status;
    00086     PCELL_DATA pparent;
    00087     PCELL_DATA pdata;
    00088     HCELL_INDEX KeyCell;
    00089     ULONG       ParentType;
    00090     ACCESS_MASK AdditionalAccess;
    00091     BOOLEAN CreateAccess;
    00092     PCM_KEY_BODY KeyBody;
    00093
    00094     CMLOG(CML_FLOW, CMS_PARSE) {
    00095         KdPrint(("CmpDoCreate:\n"));
    00096     }
    00097
    00098     if (ARGUMENT_PRESENT(Context)) {
    00099
    00100         if (Context->CreateOptions & REG_OPTION_BACKUP_RESTORE) {
    00101
    00102             //
    00103             // we're supposed to be opening for a backup/restore
    00104             // operation, but this is a new create, which makes
    00105             // no sense, so fail.
    00106             //
    00107             return STATUS_OBJECT_NAME_NOT_FOUND;
    00108         }
    00109
    00110         //
    00111         // Operation is a create, so set Disposition
    00112         //
    00113         Context->Disposition = REG_CREATED_NEW_KEY;
    00114     }
    00115
    00116     //
    00117     // Check to make sure the caller can create a sub-key here.
    00118     //
    00119     pparent = HvGetCell(Hive, Cell);
    00120     pdata = HvGetCell(Hive, pparent->u.KeyNode.Security);
    00121     ParentType = HvGetCellType(Cell);
    00122
    00123     if ( (ParentType == Volatile) &&
    00124          ((Context->CreateOptions & REG_OPTION_VOLATILE) == 0) )
    00125     {
    00126         //
    00127         // Trying to create stable child under volatile parent, report error
    00128         //
    00129         return STATUS_CHILD_MUST_BE_VOLATILE;
    00130     }
    00131
    00132     if (pparent->u.KeyNode.Flags &   KEY_SYM_LINK)
    00133     {
    00134         //
    00135         // Disallow attempts to create anything under a symbolic link
    00136         //
    00137         return STATUS_ACCESS_DENIED;
    00138     }
    00139
    00140     AdditionalAccess = (Context->CreateOptions & REG_OPTION_CREATE_LINK) ? KEY_CREATE_LINK : 0;
    00141
    00142     //
    00143     // The FullName is not used in the routine CmpCheckCreateAccess,
    00144     //
    00145     CreateAccess = CmpCheckCreateAccess(NULL,
    00146                                         &(pdata->u.KeySecurity.Descriptor),
    00147                                         AccessState,
    00148                                         AccessMode,
    00149                                         AdditionalAccess,
    00150                                         &status);
    00151
    00152     if (CreateAccess) {
    00153
    00154         //
    00155         // Security check passed, so we can go ahead and create
    00156         // the sub-key.
    00157         //
    00158         if ( !(Context->CreateOptions & REG_OPTION_VOLATILE) &&
    00159              !HvMarkCellDirty(Hive, Cell)) {
    00160
    00161             return STATUS_NO_LOG_SPACE;
    00162         }
    00163
    00164         //
    00165         // Create and initialize the new sub-key
    00166         //
    00167         status = CmpDoCreateChild( Hive,
    00168                                    Cell,
    00169                                    &(pdata->u.KeySecurity.Descriptor),
    00170                                    AccessState,
    00171                                    Name,
    00172                                    AccessMode,
    00173                                    Context,
    00174                                    ParentKcb,
    00175                                    0,
    00176                                    &KeyCell,
    00177                                    Object );
    00178
    00179         if (NT_SUCCESS(status)) {
    00180
    00181             //
    00182             // Child successfully created, add to parent's list.
    00183             //
    00184             if (! CmpAddSubKey(Hive, Cell, KeyCell)) {
    00185
    00186                 //
    00187                 // Unable to add child, so free it
    00188                 //
    00189                 CmpFreeKeyByCell(Hive, KeyCell, FALSE);
    00190                 return STATUS_INSUFFICIENT_RESOURCES;
    00191             }
    00192
    00193             //
    00194             // Update max keyname and class name length fields
    00195             //
    00196             if (pparent->u.KeyNode.MaxNameLen < Name->Length) {
    00197                 pparent->u.KeyNode.MaxNameLen = Name->Length;
    00198             }
    00199
    00200             if (pparent->u.KeyNode.MaxClassLen < Context->Class.Length) {
    00201                 pparent->u.KeyNode.MaxClassLen = Context->Class.Length;
    00202             }
    00203
    00204             KeyBody = (PCM_KEY_BODY)(*Object);
    00205
    00206             //
    00207             // A new key is created, invalid the subkey info of the parent KCB.
    00208             //
    00209             ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00210
    00211             CmpCleanUpSubKeyInfo (KeyBody->KeyControlBlock->ParentKcb);
    00212
    00213             if (Context->CreateOptions & REG_OPTION_CREATE_LINK) {
    00214                 pdata = HvGetCell(Hive, KeyCell);
    00215                 pdata->u.KeyNode.Flags |= KEY_SYM_LINK;
    00216                 KeyBody->KeyControlBlock->Flags = pdata->u.KeyNode.Flags;
    00217
    00218             }
    00219         }
    00220     }
    00221     return status;
    00222 }

NTSTATUS CmpDoCreateChild | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ParentCell,
|  | IN PSECURITY_DESCRIPTOR ParentDescriptor | OPTIONAL,
|  | IN PACCESS_STATE | AccessState,
|  | IN PUNICODE_STRING | Name,
|  | IN KPROCESSOR_MODE | AccessMode,
|  | IN PCM_PARSE_CONTEXT | Context,
|  | IN PCM_KEY_CONTROL_BLOCK | ParentKcb,
|  | IN USHORT | Flags,
|  | OUT PHCELL_INDEX | KeyCell,
|  | OUT PVOID * | Object
| ) |

Definition at line 226 of file cmparse2.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, AssignSecurityDescriptor, _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CM_KEY_NODE_SIGNATURE, CML_FLOW, CMLOG, CmpCopyName(), CmpCreateKeyControlBlock(), CmpDereferenceKeyControlBlockWithLock(), CmpHKeyNodeSize, CmpKeyObjectType, CmpRemoveKeyControlBlock(), CmpReportNotify(), CmpSecurityMethod(), CMS_PARSE, _CHILD_LIST::Count, ENLIST_KEYBODY_IN_KEYBODY_LIST, EXCEPTION_EXECUTE_HANDLER, FALSE, _CM_KEY_NODE::Flags, _OBJECT_TYPE_INITIALIZER::GenericMapping, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, kcb(), KeQuerySystemTime(), KEY_BODY_TYPE, KEY_COMP_NAME, KEY_PREDEF_HANDLE, _CM_KEY_BODY::KeyControlBlock, _CELL_DATA::_u::KeyString, _CM_KEY_NODE::LastWriteTime, _CHILD_LIST::List, _CM_KEY_NODE::MaxClassLen, _CM_KEY_NODE::MaxNameLen, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, Name, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, _CM_KEY_BODY::NotifyBlock, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, _CM_KEY_NODE::Parent, _OBJECT_TYPE_INITIALIZER::PoolType, _CM_KEY_BODY::Process, PsGetCurrentProcess, REG_OPTION_PREDEF_HANDLE, SeAssignSecurity(), _CM_KEY_NODE::Security, SeDeassignSecurity(), _CM_KEY_NODE::Signature, _CM_KEY_NODE::Spare, Stable, Status, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, _CM_KEY_BODY::Type, _OBJECT_TYPE::TypeInfo, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmpCreateLinkNode(), and CmpDoCreate().

    00242                    :
    00243
    00244     Creates a new sub-key.  This is called by CmpDoCreate to create child
    00245     sub-keys and CmpCreateLinkNode to create root sub-keys.
    00246
    00247 Arguments:
    00248
    00249     Hive - supplies a pointer to the hive control structure for the hive
    00250
    00251     ParentCell - supplies cell index of parent cell
    00252
    00253     ParentDescriptor - Supplies security descriptor of parent key, for use
    00254            in inheriting ACLs.
    00255
    00256     AccessState - Running security access state information for operation.
    00257
    00258     Name - Supplies pointer to a UNICODE string which is the name of the
    00259            child to be created.
    00260
    00261     AccessMode - Access mode of the original caller.
    00262
    00263     Context - Supplies pointer to CM_PARSE_CONTEXT structure passed through
    00264            the object manager.
    00265
    00266     BaseName - Name of object create is relative to
    00267
    00268     KeyName - Relative name (to BaseName)
    00269
    00270     Flags - Supplies any flags to be set in the newly created node
    00271
    00272     KeyCell - Receives the cell index of the newly created sub-key, if any.
    00273
    00274     Object - Receives a pointer to the created key object, if any.
    00275
    00276 Return Value:
    00277
    00278     STATUS_SUCCESS - sub-key successfully created.  New object is returned in
    00279             Object, and the new cell's cell index is returned in KeyCell.
    00280
    00281     !STATUS_SUCCESS - appropriate error message.
    00282
    00283 --*/
    00284
    00285 {
    00286     ULONG clean=0;
    00287     ULONG alloc=0;
    00288     NTSTATUS Status = STATUS_SUCCESS;
    00289     PCM_KEY_BODY KeyBody;
    00290     HCELL_INDEX ClassCell=HCELL_NIL;
    00291     PCM_KEY_NODE KeyNode;
    00292     PCELL_DATA CellData;
    00293     PCM_KEY_CONTROL_BLOCK kcb;
    00294     PCM_KEY_CONTROL_BLOCK fkcb;
    00295     LONG found;
    00296     ULONG StorageType;
    00297     PSECURITY_DESCRIPTOR NewDescriptor = NULL;
    00298     LARGE_INTEGER systemtime;
    00299
    00300     CMLOG(CML_FLOW, CMS_PARSE) {
    00301         KdPrint(("CmpDoCreateChild:\n"));
    00302     }
    00303     try {
    00304         //
    00305         // Get allocation type
    00306         //
    00307         StorageType = Stable;
    00308         if (Context->CreateOptions & REG_OPTION_VOLATILE) {
    00309             StorageType = Volatile;
    00310         }
    00311
    00312         //
    00313         // Allocate child cell
    00314         //
    00315         *KeyCell = HvAllocateCell(
    00316                         Hive,
    00317                         CmpHKeyNodeSize(Hive, Name),
    00318                         StorageType
    00319                         );
    00320         if (*KeyCell == HCELL_NIL) {
    00321                         Status = STATUS_INSUFFICIENT_RESOURCES;
    00322                         __leave;
    00323         }
    00324         alloc = 1;
    00325         KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
    00326
    00327         //
    00328         // Allocate cell for class name
    00329         //
    00330         if (Context->Class.Length > 0) {
    00331             ClassCell = HvAllocateCell(Hive, Context->Class.Length, StorageType);
    00332             if (ClassCell == HCELL_NIL) {
    00333                 Status = STATUS_INSUFFICIENT_RESOURCES;
    00334                                 __leave;
    00335             }
    00336         }
    00337         alloc = 2;
    00338         //
    00339         // Allocate the object manager object
    00340         //
    00341         Status = ObCreateObject(AccessMode,
    00342                                 CmpKeyObjectType,
    00343                                 NULL,
    00344                                 AccessMode,
    00345                                 NULL,
    00346                                 sizeof(CM_KEY_BODY),
    00347                                 0,
    00348                                 0,
    00349                                 Object);
    00350
    00351         if (NT_SUCCESS(Status)) {
    00352
    00353             KeyBody = (PCM_KEY_BODY)(*Object);
    00354
    00355             //
    00356             // We have managed to allocate all of the objects we need to,
    00357             // so initialize them
    00358             //
    00359
    00360             //
    00361             // Mark the object as uninitialized (in case we get an error too soon)
    00362             //
    00363             KeyBody->Type = KEY_BODY_TYPE;
    00364             KeyBody->KeyControlBlock = NULL;
    00365
    00366             //
    00367             // Fill in the class name
    00368             //
    00369             if (Context->Class.Length > 0) {
    00370
    00371                 CellData = HvGetCell(Hive, ClassCell);
    00372
    00373                 try {
    00374
    00375                     RtlMoveMemory(
    00376                         &(CellData->u.KeyString[0]),
    00377                         Context->Class.Buffer,
    00378                         Context->Class.Length
    00379                         );
    00380
    00381                 } except(EXCEPTION_EXECUTE_HANDLER) {
    00382                     ObDereferenceObject(*Object);
    00383                     return GetExceptionCode();
    00384                 }
    00385             }
    00386
    00387             //
    00388             // Fill in the new key itself
    00389             //
    00390             KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
    00391             KeyNode->Flags = Flags;
    00392
    00393             KeQuerySystemTime(&systemtime);
    00394             KeyNode->LastWriteTime = systemtime;
    00395
    00396             KeyNode->Spare = 0;
    00397             KeyNode->Parent = ParentCell;
    00398             KeyNode->SubKeyCounts[Stable] = 0;
    00399             KeyNode->SubKeyCounts[Volatile] = 0;
    00400             KeyNode->SubKeyLists[Stable] = HCELL_NIL;
    00401             KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
    00402             KeyNode->ValueList.Count = 0;
    00403             KeyNode->ValueList.List = HCELL_NIL;
    00404             KeyNode->Security = HCELL_NIL;
    00405             KeyNode->Class = ClassCell;
    00406             KeyNode->ClassLength = Context->Class.Length;
    00407
    00408             KeyNode->MaxValueDataLen = 0;
    00409             KeyNode->MaxNameLen = 0;
    00410             KeyNode->MaxValueNameLen = 0;
    00411             KeyNode->MaxClassLen = 0;
    00412
    00413             KeyNode->NameLength = CmpCopyName(Hive,
    00414                                               KeyNode->Name,
    00415                                               Name);
    00416             if (KeyNode->NameLength < Name->Length) {
    00417                 KeyNode->Flags |= KEY_COMP_NAME;
    00418             }
    00419
    00420             if (Context->CreateOptions & REG_OPTION_PREDEF_HANDLE) {
    00421                 KeyNode->ValueList.Count = (ULONG)((ULONG_PTR)Context->PredefinedHandle);
    00422                 KeyNode->Flags |= KEY_PREDEF_HANDLE;
    00423             }
    00424
    00425             //
    00426             // Create kcb here so all data are filled in.
    00427             //
    00428             // Allocate a key control block
    00429             //
    00430             kcb = CmpCreateKeyControlBlock(Hive, *KeyCell, KeyNode, ParentKcb, FALSE, Name);
    00431             if (kcb == NULL) {
    00432                 ObDereferenceObject(*Object);
    00433                 return STATUS_INSUFFICIENT_RESOURCES;
    00434             }
    00435             ASSERT(kcb->RefCount == 1);
    00436             alloc = 3;
    00437
    00438             //
    00439             // Fill in CM specific fields in the object
    00440             //
    00441             KeyBody->Type = KEY_BODY_TYPE;
    00442             KeyBody->KeyControlBlock = kcb;
    00443             KeyBody->NotifyBlock = NULL;
    00444             KeyBody->Process = PsGetCurrentProcess();
    00445             ENLIST_KEYBODY_IN_KEYBODY_LIST(KeyBody);
    00446             //
    00447             // Assign a security descriptor to the object.  Note that since
    00448             // registry keys are container objects, and ObAssignSecurity
    00449             // assumes that the only container object in the world is
    00450             // the ObpDirectoryObjectType, we have to call SeAssignSecurity
    00451             // directly in order to get the right inheritance.
    00452             //
    00453
    00454             Status = SeAssignSecurity(ParentDescriptor,
    00455                                       AccessState->SecurityDescriptor,
    00456                                       &NewDescriptor,
    00457                                       TRUE,             // container object
    00458                                       &AccessState->SubjectSecurityContext,
    00459                                       &CmpKeyObjectType->TypeInfo.GenericMapping,
    00460                                       CmpKeyObjectType->TypeInfo.PoolType);
    00461             if (NT_SUCCESS(Status)) {
    00462                 Status = CmpSecurityMethod(*Object,
    00463                                            AssignSecurityDescriptor,
    00464                                            NULL,
    00465                                            NewDescriptor,
    00466                                            NULL,
    00467                                            NULL,
    00468                                            CmpKeyObjectType->TypeInfo.PoolType,
    00469                                            &CmpKeyObjectType->TypeInfo.GenericMapping);
    00470             }
    00471
    00472             //
    00473             // Since the security descriptor now lives in the hive,
    00474             // free the in-memory copy
    00475             //
    00476             SeDeassignSecurity( &NewDescriptor );
    00477
    00478             if (!NT_SUCCESS(Status)) {
    00479
    00480                 //
    00481                 // Note that the dereference will clean up the kcb, so
    00482                 // make sure and decrement the allocation count here.
    00483                 //
    00484                 // Also mark the kcb as deleted so it does not get
    00485                 // inappropriately cached.
    00486                 //
    00487                 ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00488                 kcb->Delete = TRUE;
    00489                 CmpRemoveKeyControlBlock(kcb);
    00490                 ObDereferenceObject(*Object);
    00491                 alloc = 2;
    00492
    00493             } else {
    00494                 CmpReportNotify(
    00495                         kcb,
    00496                         kcb->KeyHive,
    00497                         kcb->KeyCell,
    00498                         REG_NOTIFY_CHANGE_NAME
    00499                         );
    00500             }
    00501         }
    00502
    00503     } finally {
    00504
    00505         if (!NT_SUCCESS(Status)) {
    00506
    00507             //
    00508             // Clean up allocations
    00509             //
    00510             switch (alloc) {
    00511             case 3:
    00512                 //
    00513                 // Mark KCB as deleted so it does not get inadvertently added to
    00514                 // the delayed close list. That would have fairly disastrous effects
    00515                 // as the KCB points to storage we are about to free.
    00516                 //
    00517                 ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00518                 kcb->Delete = TRUE;
    00519                 CmpRemoveKeyControlBlock(kcb);
    00520                 CmpDereferenceKeyControlBlockWithLock(kcb);
    00521                 // DELIBERATE FALL
    00522
    00523             case 2:
    00524                 if (Context->Class.Length > 0) {
    00525                     HvFreeCell(Hive, ClassCell);
    00526                 }
    00527                 // DELIBERATE FALL
    00528
    00529             case 1:
    00530                 HvFreeCell(Hive, *KeyCell);
    00531                 // DELIBERATE FALL
    00532             }
    00533         }
    00534     }
    00535
    00536     return(Status);
    00537 }
    }

NTSTATUS CmpDoFileSetSize | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | ULONG | FileSize
| ) |

Definition at line 227 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CmpIoFileSetSize, CmRegistryIODebug, DbgPrint, FALSE, _CMHIVE::FileHandles, Hive, IoSetThreadHardErrorMode(), L, NT_SUCCESS, NTSTATUS(), NULL, Status, TRUE, and ZwSetInformationFile().

Referenced by CmpFileSetSize(), CmpWorker(), CmpWorkerCommand(), HvpDoWriteHive(), and HvWriteHive().

    00234                    :
    00235
    00236     This routine sets the size of a file.  It must not return until
    00237     the size is guaranteed.
    00238
    00239     It is environment specific.
    00240
    00241     Must be running in the context of the cmp worker thread.
    00242
    00243 Arguments:
    00244
    00245     Hive - Hive we are doing I/O for
    00246
    00247     FileType - which supporting file to use
    00248
    00249     FileSize - 32 bit value to set the file's size to
    00250
    00251 Return Value:
    00252
    00253     FALSE if failure
    00254     TRUE if success
    00255
    00256 --*/
    00257 {
    00258     PCMHIVE CmHive;
    00259     HANDLE  FileHandle;
    00260     NTSTATUS Status;
    00261     FILE_END_OF_FILE_INFORMATION FileInfo;
    00262     IO_STATUS_BLOCK IoStatus;
    00263     BOOLEAN oldFlag;
    00264
    00265     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00266
    00267     CmHive = (PCMHIVE)Hive;
    00268     FileHandle = CmHive->FileHandles[FileType];
    00269     if (FileHandle == NULL) {
    00270         return TRUE;
    00271     }
    00272
    00273     //
    00274     // disable hard error popups, to avoid self deadlock on bogus devices
    00275     //
    00276     oldFlag = IoSetThreadHardErrorMode(FALSE);
    00277
    00278     FileInfo.EndOfFile.HighPart = 0L;
    00279     FileInfo.EndOfFile.LowPart  = FileSize;
    00280
    00281     ASSERT_PASSIVE_LEVEL();
    00282
    00283     Status = ZwSetInformationFile(
    00284                 FileHandle,
    00285                 &IoStatus,
    00286                 (PVOID)&FileInfo,
    00287                 sizeof(FILE_END_OF_FILE_INFORMATION),
    00288                 FileEndOfFileInformation
    00289                 );
    00290
    00291     if (NT_SUCCESS(Status)) {
    00292         ASSERT(IoStatus.Status == Status);
    00293     } else {
    00294
    00295         //
    00296         // set debugging info
    00297         //
    00298         CmRegistryIODebug.Action = CmpIoFileSetSize;
    00299         CmRegistryIODebug.Handle = FileHandle;
    00300         CmRegistryIODebug.Status = Status;
    00301         DbgPrint("CmpFileSetSize:\tHandle=%08lx  NewLength=%08lx  \n", FileHandle, FileSize);
    00302     }
    00303
    00304     //
    00305     // restore hard error popups mode
    00306     //
    00307     IoSetThreadHardErrorMode(oldFlag);
    00308
    00309     return Status;
    00310 }

BOOLEAN CmpDoFlushAll | ( | VOID |  | ) |

Definition at line 2195 of file cmapi.c.

References CmLockHive, CmpHiveListHead, CmpMasterHive, CmpNoWrite, CmUnlockHive, FALSE, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HiveList, HvSyncHive(), NT_SUCCESS, NTSTATUS(), Status, and TRUE.

Referenced by CmFlushKey(), CmpLazyFlushWorker(), and CmpWorker().

    02200                    :
    02201
    02202     Flush all hives.
    02203
    02204     Runs in the context of the CmpWorkerThread.
    02205
    02206     Runs down list of Hives and applies HvSyncHive to them.
    02207
    02208     NOTE: Hives which are marked as HV_NOLAZYFLUSH are *NOT* flushed
    02209           by this call.  You must call HvSyncHive explicitly to flush
    02210           a hive marked as HV_NOLAZYFLUSH.
    02211
    02212 Arguments:
    02213
    02214 Return Value:
    02215
    02216     NONE
    02217
    02218 --*/
    02219 {
    02220     NTSTATUS    Status;
    02221     PLIST_ENTRY p;
    02222     PCMHIVE     h;
    02223     BOOLEAN     Result = TRUE;
    02224 /*
    02225     ULONG rc;
    02226 */
    02227     extern PCMHIVE CmpMasterHive;
    02228
    02229     //
    02230     // If writes are not working, lie and say we succeeded, will
    02231     // clean up in a short time.  Only early system init code
    02232     // will ever know the difference.
    02233     //
    02234     if (CmpNoWrite) {
    02235         return TRUE;
    02236     }
    02237
    02238     //
    02239     // traverse list of hives, sync each one
    02240     //
    02241     p = CmpHiveListHead.Flink;
    02242     while (p != &CmpHiveListHead) {
    02243
    02244         h = CONTAINING_RECORD(p, CMHIVE, HiveList);
    02245
    02246 /*
    02247 #if DBG
    02248         if (h!=CmpMasterHive) {
    02249             rc = CmCheckRegistry(h, FALSE);
    02250
    02251             if (rc!=0) {
    02252                 KdPrint(("CmpDoFlushAll: corrupt hive, rc = %08lx\n",rc));
    02253                 DbgBreakPoint();
    02254             }
    02255         }
    02256 #endif
    02257 */
    02258         if (!(h->Hive.HiveFlags & HIVE_NOLAZYFLUSH)) {
    02259
    02260             //
    02261             //Lock the hive before we flush it.
    02262             //-- since we now allow multiple readers
    02263             // during a flush (a flush is considered a read)
    02264             // we have to force a serialization on the vector table
    02265             //
    02266             CmLockHive (h);
    02267
    02268             Status = HvSyncHive((PHHIVE)h);
    02269
    02270             if( !NT_SUCCESS( Status ) ) {
    02271                 Result = FALSE;
    02272             }
    02273             CmUnlockHive (h);
    02274             //
    02275             // WARNNOTE - the above means that a lazy flush or
    02276             //            or shutdown flush did not work.  we don't
    02277             //            know why.  there is noone to report an error
    02278             //            to, so continue on and hope for the best.
    02279             //            (in theory, worst that can happen is user changes
    02280             //             are lost.)
    02281             //
    02282         }
    02283
    02284
    02285         p = p->Flink;
    02286     }
    02287
    02288     return Result;
    02289 }

BOOLEAN CmpFileFlush | ( | PHHIVE | Hive,
|  | ULONG | FileType
| ) |

Definition at line 772 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpIoFileFlush, CmpNoWrite, CmRegistryIODebug, CMS_IO, DbgPrint, FALSE, _CMHIVE::FileHandles, Hive, NT_SUCCESS, NTSTATUS(), NULL, and TRUE.

Referenced by CmpInitializeHive(), and CmpSaveKeyByFileCopy().

    00778                    :
    00779
    00780     This routine performs a flush on a file handle.
    00781
    00782 Arguments:
    00783
    00784     Hive - Hive we are doing I/O for
    00785
    00786     FileType - which supporting file to use
    00787
    00788 Return Value:
    00789
    00790     FALSE if failure
    00791     TRUE if success
    00792
    00793 --*/
    00794 {
    00795     NTSTATUS status;
    00796     IO_STATUS_BLOCK IoStatus;
    00797     PCMHIVE CmHive;
    00798     HANDLE  FileHandle;
    00799
    00800     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00801     CmHive = (PCMHIVE)Hive;
    00802     FileHandle = CmHive->FileHandles[FileType];
    00803     if (FileHandle == NULL) {
    00804         return TRUE;
    00805     }
    00806
    00807     if (CmpNoWrite) {
    00808         return TRUE;
    00809     }
    00810
    00811     CMLOG(CML_MAJOR, CMS_IO) {
    00812         KdPrint(("CmpFileFlush:\n\tHandle = %08lx\n", FileHandle));
    00813     }
    00814
    00815     ASSERT_PASSIVE_LEVEL();
    00816
    00817     status = ZwFlushBuffersFile(
    00818                 FileHandle,
    00819                 &IoStatus
    00820                 );
    00821
    00822     if (NT_SUCCESS(status)) {
    00823         ASSERT(IoStatus.Status == status);
    00824         return TRUE;
    00825     } else {
    00826         //
    00827         // set debugging info
    00828         //
    00829         CmRegistryIODebug.Action = CmpIoFileFlush;
    00830         CmRegistryIODebug.Handle = FileHandle;
    00831         CmRegistryIODebug.Status = status;
    00832         DbgPrint("CmpFileFlush:\tFailure1: status = %08lx  IoStatus = %08lx\n",status,IoStatus.Status);
    00833         return FALSE;
    00834     }
    00835     return TRUE;
    00836 }
    }

BOOLEAN CmpFileRead | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | PULONG | FileOffset,
|  | PVOID | DataBuffer,
|  | ULONG | DataLength
| ) |

Definition at line 351 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpCreateEvent(), CmpIoFileRead, CmRegistryIODebug, CMS_IO, CMS_IO_ERROR, DbgPrint, Executive, FALSE, _CMHIVE::FileHandles, Hive, KernelMode, KeWaitForSingleObject(), L, MAX_FILE_IO, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, Offset, and TRUE.

Referenced by CmpInitializeHive(), and CmpWorker().

    00360                    :
    00361
    00362     This routine reads in a buffer from a file.
    00363
    00364     It is environment specific.
    00365
    00366     NOTE:   We assume the handle is opened for asynchronous access,
    00367             and that we, and not the IO system, are keeping the
    00368             offset pointer.
    00369
    00370     NOTE:   Only 32bit offsets are supported, even though the underlying
    00371             IO system on NT supports 64 bit offsets.
    00372
    00373 Arguments:
    00374
    00375     Hive - Hive we are doing I/O for
    00376
    00377     FileType - which supporting file to use
    00378
    00379     FileOffset - pointer to variable providing 32bit offset on input,
    00380                  and receiving new 32bit offset on output.
    00381
    00382     DataBuffer - pointer to buffer
    00383
    00384     DataLength - length of buffer
    00385
    00386 Return Value:
    00387
    00388     FALSE if failure
    00389     TRUE if success
    00390
    00391 --*/
    00392 {
    00393     NTSTATUS status;
    00394     LARGE_INTEGER   Offset;
    00395     IO_STATUS_BLOCK IoStatus;
    00396     PCMHIVE CmHive;
    00397     HANDLE  FileHandle;
    00398     ULONG LengthToRead;
    00399     HANDLE eventHandle = NULL;
    00400     PKEVENT eventObject = NULL;
    00401
    00402     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00403     CmHive = (PCMHIVE)Hive;
    00404     FileHandle = CmHive->FileHandles[FileType];
    00405     if (FileHandle == NULL) {
    00406         return TRUE;
    00407     }
    00408
    00409     CMLOG(CML_MAJOR, CMS_IO) {
    00410         KdPrint(("CmpFileRead:\n"));
    00411         KdPrint(("\tHandle=%08lx  Offset=%08lx  ", FileHandle, *FileOffset));
    00412         KdPrint(("Buffer=%08lx  Length=%08lx\n", DataBuffer, DataLength));
    00413     }
    00414
    00415     //
    00416     // Detect attempt to read off end of 2gig file (this should be irrelevent)
    00417     //
    00418     if ((0xffffffff - *FileOffset) < DataLength) {
    00419         CMLOG(CML_MAJOR, CMS_IO_ERROR) KdPrint(("CmpFileRead: runoff\n"));
    00420         return FALSE;
    00421     }
    00422
    00423     status = CmpCreateEvent(
    00424         SynchronizationEvent,
    00425         &eventHandle,
    00426         &eventObject);
    00427     if (!NT_SUCCESS(status))
    00428         return FALSE;
    00429
    00430     //
    00431     // We'd really like to just call the filesystems and have them do
    00432     // the right thing.  But the filesystem will attempt to lock our
    00433     // entire buffer into memory, and that may fail for large requests.
    00434     // So we split our reads into 64k chunks and call the filesystem for
    00435     // each one.
    00436     //
    00437     ASSERT_PASSIVE_LEVEL();
    00438     while (DataLength > 0) {
    00439
    00440         //
    00441         // Convert ULONG to Large
    00442         //
    00443         Offset.LowPart = *FileOffset;
    00444         Offset.HighPart = 0L;
    00445
    00446         //
    00447         // trim request down if necessary.
    00448         //
    00449         if (DataLength > MAX_FILE_IO) {
    00450             LengthToRead = MAX_FILE_IO;
    00451         } else {
    00452             LengthToRead = DataLength;
    00453         }
    00454
    00455         status = ZwReadFile(
    00456                     FileHandle,
    00457                     eventHandle,
    00458                     NULL,               // apcroutine
    00459                     NULL,               // apccontext
    00460                     &IoStatus,
    00461                     DataBuffer,
    00462                     LengthToRead,
    00463                     &Offset,
    00464                     NULL                // key
    00465                     );
    00466
    00467         if (STATUS_PENDING == status) {
    00468             status = KeWaitForSingleObject(eventObject, Executive,
    00469                                            KernelMode, FALSE, NULL);
    00470             ASSERT(STATUS_SUCCESS == status);
    00471             status = IoStatus.Status;
    00472         }
    00473
    00474         //
    00475         // adjust offsets
    00476         //
    00477         *FileOffset = Offset.LowPart + LengthToRead;
    00478         DataLength -= LengthToRead;
    00479         (PUCHAR)DataBuffer += LengthToRead;
    00480
    00481         if (NT_SUCCESS(status)) {
    00482             ASSERT(IoStatus.Status == status);
    00483             if (IoStatus.Information != LengthToRead) {
    00484                 CMLOG(CML_MAJOR, CMS_IO_ERROR) {
    00485                     KdPrint(("CmpFileRead:\n\t"));
    00486                     KdPrint(("Failure1: status = %08lx  ", status));
    00487                     KdPrint(("IoInformation = %08lx\n", IoStatus.Information));
    00488                 }
    00489                 ObDereferenceObject(eventObject);
    00490                 ZwClose(eventHandle);
    00491                 return FALSE;
    00492             }
    00493         } else {
    00494             //
    00495             // set debugging info
    00496             //
    00497             CmRegistryIODebug.Action = CmpIoFileRead;
    00498             CmRegistryIODebug.Handle = FileHandle;
    00499             CmRegistryIODebug.Status = status;
    00500             DbgPrint("CmpFileRead:\tFailure2: status = %08lx  IoStatus = %08lx\n", status, IoStatus.Status);
    00501
    00502             ObDereferenceObject(eventObject);
    00503             ZwClose(eventHandle);
    00504             return FALSE;
    00505         }
    00506
    00507     }
    00508     ObDereferenceObject(eventObject);
    00509     ZwClose(eventHandle);
    00510     return TRUE;
    00511 }

BOOLEAN CmpFileSetSize | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | ULONG | FileSize
| ) |

Definition at line 45 of file cmwrapr2.c.

References CML_MAJOR, CMLOG, CmpDoFileSetSize(), CMS_IO_ERROR, FALSE, Hive, NT_SUCCESS, NTSTATUS(), and TRUE.

Referenced by CmpInitializeHive(), and CmpInitializeHiveList().

    00052                    :
    00053
    00054     This routine sets the size of a file.  It must not return until
    00055     the size is guaranteed, therefore, it does a flush.
    00056
    00057     It is environment specific.
    00058
    00059     This routine will force execution to the correct thread context.
    00060
    00061 Arguments:
    00062
    00063     Hive - Hive we are doing I/O for
    00064
    00065     FileType - which supporting file to use
    00066
    00067     FileSize - 32 bit value to set the file's size to
    00068
    00069 Return Value:
    00070
    00071     FALSE if failure
    00072     TRUE if success
    00073
    00074 --*/
    00075 {
    00076     NTSTATUS    status;
    00077     REGISTRY_COMMAND Command;
    00078
    00079     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00080
    00081     //
    00082     // Wake up worker thread to do real work for us.
    00083     //
    00084     Command.Command  = REG_CMD_FILE_SET_SIZE;
    00085     Command.Hive     = Hive;
    00086     Command.FileType = FileType;
    00087     Command.FileSize = FileSize;
    00088     CmpLockRegistryExclusive();
    00089     CmpWorker(&Command);
    00090     status = Command.Status;
    00091     CmpUnlockRegistry();
    00092
    00093     if (!NT_SUCCESS(status)) {
    00094         CMLOG(CML_MAJOR, CMS_IO_ERROR) {
    00095             KdPrint(("CmpFileSetSize:\n\t"));
    00096             KdPrint(("Failure: status = %08lx ", status));
    00097         }
    00098         return FALSE;
    00099     }
    00100
    00101     return TRUE;
    00102 }
    }

BOOLEAN CmpFileWrite | ( | PHHIVE | Hive,
|  | ULONG | FileType,
|  | PCMP_OFFSET_ARRAY | offsetArray,
|  | ULONG | offsetArrayCount,
|  | PULONG | FileOffset
| ) |

Definition at line 516 of file cmwrapr.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CML_MAJOR, CMLOG, CmpCreateEvent(), CmpIoFileWrite, CmpNoWrite, CmRegistryIODebug, CMS_IO, CMS_IO_ERROR, DbgPrint, Executive, FALSE, _CMHIVE::FileHandles, Hive, KernelMode, KeWaitForMultipleObjects(), L, MAX_FILE_IO, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, Offset, PAGE_SIZE, perftouchbuffer, Status, and TRUE.

Referenced by CmpInitializeHive(), and CmpSaveKeyByFileCopy().

    00525                    :
    00526
    00527     This routine writes an array of buffers out to a file.
    00528
    00529     It is environment specific.
    00530
    00531     NOTE:   We assume the handle is opened for asynchronous access,
    00532             and that we, and not the IO system, are keeping the
    00533             offset pointer.
    00534
    00535     NOTE:   Only 32bit offsets are supported, even though the underlying
    00536             IO system on NT supports 64 bit offsets.
    00537
    00538 Arguments:
    00539
    00540     Hive - Hive we are doing I/O for
    00541
    00542     FileType - which supporting file to use
    00543
    00544     offsetArray - array of structures where each structure holds a 32bit offset
    00545                   into the Hive file and pointer the a buffer written to that
    00546                   file offset.
    00547
    00548     offsetArrayCount - number of elements in the offsetArray.
    00549
    00550     FileOffset - returns the file offset after the last write to the file.
    00551
    00552 Return Value:
    00553
    00554     FALSE if failure
    00555     TRUE if success
    00556
    00557 --*/
    00558 {
    00559     NTSTATUS status;
    00560     LARGE_INTEGER   Offset;
    00561     PCMHIVE CmHive;
    00562     HANDLE  FileHandle;
    00563     ULONG LengthToWrite;
    00564     LONG WaitBufferCount = 0;
    00565     LONG idx;
    00566     ULONG arrayCount = 0;
    00567     PVOID       DataBuffer;
    00568     ULONG       DataLength;
    00569     HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS];
    00570     PKEVENT eventObjects[MAXIMUM_WAIT_OBJECTS];
    00571     KWAIT_BLOCK waitBlockArray[MAXIMUM_WAIT_OBJECTS];
    00572     IO_STATUS_BLOCK IoStatus[MAXIMUM_WAIT_OBJECTS];
    00573     BOOLEAN ret_val = TRUE;
    00574
    00575     if (CmpNoWrite) {
    00576         return TRUE;
    00577     }
    00578
    00579     ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
    00580     CmHive = (PCMHIVE)Hive;
    00581     FileHandle = CmHive->FileHandles[FileType];
    00582     if (FileHandle == NULL) {
    00583         return TRUE;
    00584     }
    00585
    00586     CMLOG(CML_MAJOR, CMS_IO) {
    00587         KdPrint(("CmpFileWrite:\n"));
    00588         KdPrint(("\tHandle=%08lx  ", FileHandle));
    00589     }
    00590
    00591     for (idx = 0; idx < MAXIMUM_WAIT_OBJECTS; idx++) {
    00592         eventHandles[idx] = NULL;
    00593     }
    00594
    00595     // Bring pages being written into memory first to allow disk to write
    00596     // buffer contiguously.
    00597     for (idx = 0; (ULONG) idx < offsetArrayCount; idx++) {
    00598         char * start = offsetArray[idx].DataBuffer;
    00599         char * end = (char *) start + offsetArray[idx].DataLength;
    00600         while (start < end) {
    00601             // perftouchbuffer globally declared so that compiler won't try
    00602             // to remove it and this loop (if its smart enough?).
    00603             perftouchbuffer += (ULONG) *start;
    00604             start += PAGE_SIZE;
    00605         }
    00606     }
    00607
    00608     //
    00609     // We'd really like to just call the filesystems and have them do
    00610     // the right thing.  But the filesystem will attempt to lock our
    00611     // entire buffer into memory, and that may fail for large requests.
    00612     // So we split our reads into 64k chunks and call the filesystem for
    00613     // each one.
    00614     //
    00615     ASSERT_PASSIVE_LEVEL();
    00616     arrayCount = 0;
    00617     DataLength = 0;
    00618     // This outer loop is hit more than once if the MAXIMUM_WAIT_OBJECTS limit
    00619     // is hit before the offset array is drained.
    00620     while (arrayCount < offsetArrayCount) {
    00621         WaitBufferCount = 0;
    00622
    00623         // This loop fills the wait buffer.
    00624         while ((arrayCount < offsetArrayCount) &&
    00625                (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {
    00626
    00627             // If data length isn't zero than the wait buffer filled before the
    00628             // buffer in the last offsetArray element was sent to write file.
    00629             if (DataLength == 0) {
    00630                 *FileOffset = offsetArray[arrayCount].FileOffset;
    00631                 DataBuffer =  offsetArray[arrayCount].DataBuffer;
    00632                 DataLength =  offsetArray[arrayCount].DataLength;
    00633                 //
    00634                 // Detect attempt to read off end of 2gig file
    00635                 // (this should be irrelevent)
    00636                 //
    00637                 if ((0xffffffff - *FileOffset) < DataLength) {
    00638                     CMLOG(CML_MAJOR, CMS_IO_ERROR) KdPrint(("CmpFileWrite: runoff\n"));
    00639                     goto Error_Exit;
    00640                 }
    00641             }
    00642             // else still more to write out of last buffer.
    00643
    00644             while ((DataLength > 0) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {
    00645
    00646                 //
    00647                 // Convert ULONG to Large
    00648                 //
    00649                 Offset.LowPart = *FileOffset;
    00650                 Offset.HighPart = 0L;
    00651
    00652                 //
    00653                 // trim request down if necessary.
    00654                 //
    00655                 if (DataLength > MAX_FILE_IO) {
    00656                     LengthToWrite = MAX_FILE_IO;
    00657                 } else {
    00658                     LengthToWrite = DataLength;
    00659                 }
    00660
    00661                 // Previously created events are reused.
    00662                 if (eventHandles[WaitBufferCount] == NULL) {
    00663                     status = CmpCreateEvent(SynchronizationEvent,
    00664                                             &eventHandles[WaitBufferCount],
    00665                                             &eventObjects[WaitBufferCount]);
    00666                     if (!NT_SUCCESS(status)) {
    00667                         // Make sure we don't try to clean this up.
    00668                         eventHandles[WaitBufferCount] = NULL;
    00669                         goto Error_Exit;
    00670                     }
    00671                 }
    00672
    00673                 status = ZwWriteFile(FileHandle,
    00674                                      eventHandles[WaitBufferCount],
    00675                                      NULL,               // apcroutine
    00676                                      NULL,               // apccontext
    00677                                      &IoStatus[WaitBufferCount],
    00678                                      DataBuffer,
    00679                                      LengthToWrite,
    00680                                      &Offset,
    00681                                      NULL);
    00682
    00683                 if (!NT_SUCCESS(status)) {
    00684                     goto Error_Exit;
    00685                 }
    00686
    00687                 WaitBufferCount++;
    00688
    00689                 //
    00690                 // adjust offsets
    00691                 //
    00692                 *FileOffset = Offset.LowPart + LengthToWrite;
    00693                 DataLength -= LengthToWrite;
    00694                 (PUCHAR)DataBuffer += LengthToWrite;
    00695             } // while (DataLength > 0 && WaitBufferCount < MAXIMUM_WAIT_OBJECTS)
    00696
    00697             arrayCount++;
    00698
    00699         } // while (arrayCount < offsetArrayCount &&
    00700           //        WaitBufferCount < MAXIMUM_WAIT_OBJECTS)
    00701
    00702         status = KeWaitForMultipleObjects(WaitBufferCount,
    00703                                           eventObjects,
    00704                                           WaitAll,
    00705                                           Executive,
    00706                                           KernelMode,
    00707                                           FALSE,
    00708                                           NULL,
    00709                                           waitBlockArray);
    00710
    00711         if (!NT_SUCCESS(status))
    00712             goto Error_Exit;
    00713
    00714         for (idx = 0; idx < WaitBufferCount; idx++) {
    00715             if (!NT_SUCCESS(IoStatus[idx].Status)) {
    00716                 ret_val = FALSE;
    00717                 goto Done;
    00718             }
    00719         }
    00720
    00721         // There may still be more to do if the last element held a big buffer
    00722         // and the wait buffer filled before it was all sent to the file.
    00723         if (DataLength > 0) {
    00724             arrayCount--;
    00725         }
    00726
    00727     } // while (arrayCount < offsetArrayCount)
    00728
    00729     ret_val = TRUE;
    00730
    00731     goto Done;
    00732 Error_Exit:
    00733     //
    00734     // set debugging info
    00735     //
    00736     CmRegistryIODebug.Action = CmpIoFileWrite;
    00737     CmRegistryIODebug.Handle = FileHandle;
    00738     CmRegistryIODebug.Status = status;
    00739     DbgPrint("CmpFileWrite: error exiting %d\n", status);
    00740     //
    00741     // if WaitBufferCount > 0 then we have successfully issued
    00742     // some I/Os, but not all of them. This is an error, but we
    00743     // cannot return from this routine until all the successfully
    00744     // issued I/Os have completed.
    00745     //
    00746     if (WaitBufferCount > 0) {
    00747         status = KeWaitForMultipleObjects(WaitBufferCount,
    00748                                           eventObjects,
    00749                                           WaitAll,
    00750                                           Executive,
    00751                                           KernelMode,
    00752                                           FALSE,
    00753                                           NULL,
    00754                                           waitBlockArray);
    00755     }
    00756
    00757
    00758     ret_val = FALSE;
    00759 Done:
    00760     idx = 0;
    00761     // Clean up open event handles and objects.
    00762     while ((idx < MAXIMUM_WAIT_OBJECTS) && (eventHandles[idx] != NULL)) {
    00763         ObDereferenceObject(eventObjects[idx]);
    00764         ZwClose(eventHandles[idx]);
    00765         idx++;
    00766     }
    00767     return ret_val;
    00768 }

HCELL_INDEX CmpFindControlSet | ( | IN PHHIVE | SystemHive,
|  | IN HCELL_INDEX | RootCell,
|  | IN PUNICODE_STRING | SelectName,
|  | OUT PBOOLEAN | AutoSelect
| ) |

Definition at line 1082 of file cmboot.c.

References CHAR, CmpFindSubKeyByName(), CmpFindValueByName, CmpValueToData, FALSE, HCELL_INDEX, HCELL_NIL, HvGetCell, Index, L, Name, NT_SUCCESS, NTSTATUS(), PHCELL_INDEX, RtlAnsiStringToUnicodeString(), RtlInitUnicodeString(), sprintf(), Status, strlen(), TRUE, and _CM_KEY_VALUE::Type.

Referenced by CmGetSystemControlValues(), and CmGetSystemDriverList().

    01091                    :
    01092
    01093     This routines parses the SYSTEM hive and "Select" node
    01094     to locate the control set to be used for booting.
    01095
    01096     Note that this routines also updates the value of Current to reflect
    01097     the control set that was just found.  This is what we want to do
    01098     when this is called during boot.  During I/O initialization, this
    01099     is irrelevant, since we're just changing it to what it already is.
    01100
    01101 Arguments:
    01102
    01103     SystemHive - Supplies the hive control structure for the SYSTEM hive.
    01104
    01105     RootCell - Supplies the HCELL_INDEX of the root cell of the hive.
    01106
    01107     SelectName - Supplies the name of the Select value to be used in
    01108             determining the control set.  This should be one of "Current"
    01109             "Default" or "LastKnownGood"
    01110
    01111     AutoSelect - Returns the value of the AutoSelect value under
    01112             the Select node.
    01113
    01114 Return Value:
    01115
    01116     != HCELL_NIL - Cell Index of the control set to be used for booting.
    01117     == HCELL_NIL - Indicates the hive is corrupt or inconsistent
    01118
    01119 --*/
    01120
    01121 {
    01122     HCELL_INDEX Select;
    01123     HCELL_INDEX ValueCell;
    01124     HCELL_INDEX ControlSet;
    01125     HCELL_INDEX AutoSelectCell;
    01126     NTSTATUS Status;
    01127     UNICODE_STRING Name;
    01128     ANSI_STRING AnsiString;
    01129     PHCELL_INDEX Index;
    01130     PCM_KEY_VALUE Value;
    01131     PULONG ControlSetIndex;
    01132     PULONG CurrentControl;
    01133     CHAR AsciiBuffer[128];
    01134     WCHAR UnicodeBuffer[128];
    01135     ULONG realsize;
    01136
    01137     //
    01138     // Find \SYSTEM\SELECT node.
    01139     //
    01140     RtlInitUnicodeString(&Name, L"select");
    01141     Select = CmpFindSubKeyByName(SystemHive,
    01142                                 (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell),
    01143                                 &Name);
    01144     if (Select == HCELL_NIL) {
    01145         return(HCELL_NIL);
    01146     }
    01147
    01148     //
    01149     // Find AutoSelect value
    01150     //
    01151     RtlInitUnicodeString(&Name, L"AutoSelect");
    01152     AutoSelectCell = CmpFindValueByName(SystemHive,
    01153                                         (PCM_KEY_NODE)HvGetCell(SystemHive,Select),
    01154                                         &Name);
    01155     if (AutoSelectCell == HCELL_NIL) {
    01156         //
    01157         // It's not there, we don't care.  Set autoselect to TRUE
    01158         //
    01159         *AutoSelect = TRUE;
    01160     } else {
    01161         Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
    01162         *AutoSelect = *(PBOOLEAN)(CmpValueToData(SystemHive,Value,realsize));
    01163     }
    01164
    01165     ValueCell = CmpFindValueByName(SystemHive,
    01166                                    (PCM_KEY_NODE)HvGetCell(SystemHive,Select),
    01167                                    SelectName);
    01168     if (ValueCell == HCELL_NIL) {
    01169         return(HCELL_NIL);
    01170     }
    01171     Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
    01172     if (Value->Type != REG_DWORD) {
    01173         return(HCELL_NIL);
    01174     }
    01175
    01176     ControlSetIndex = (PULONG)CmpValueToData(SystemHive, Value,realsize);
    01177
    01178     //
    01179     // Find appropriate control set
    01180     //
    01181
    01182     sprintf(AsciiBuffer, "ControlSet%03d", *ControlSetIndex);
    01183     AnsiString.Length = AnsiString.MaximumLength = strlen(&(AsciiBuffer[0]));
    01184     AnsiString.Buffer = AsciiBuffer;
    01185     Name.MaximumLength = 128*sizeof(WCHAR);
    01186     Name.Buffer = UnicodeBuffer;
    01187     Status = RtlAnsiStringToUnicodeString(&Name,
    01188                                           &AnsiString,
    01189                                           FALSE);
    01190     if (!NT_SUCCESS(Status)) {
    01191         return(HCELL_NIL);
    01192     }
    01193     ControlSet = CmpFindSubKeyByName(SystemHive,
    01194                                      (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell),
    01195                                      &Name);
    01196     if (ControlSet == HCELL_NIL) {
    01197         return(HCELL_NIL);
    01198     }
    01199
    01200     //
    01201     // Control set was successfully found, so update the value in "Current"
    01202     // to reflect the control set we are going to use.
    01203     //
    01204     RtlInitUnicodeString(&Name, L"Current");
    01205     ValueCell = CmpFindValueByName(SystemHive,
    01206                                    (PCM_KEY_NODE)HvGetCell(SystemHive,Select),
    01207                                    &Name);
    01208     if (ValueCell != HCELL_NIL) {
    01209         Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
    01210         if (Value->Type == REG_DWORD) {
    01211             CurrentControl = (PULONG)CmpValueToData(SystemHive, Value,realsize);
    01212             *CurrentControl = *ControlSetIndex;
    01213         }
    01214     }
    01215     return(ControlSet);
    01216
    01217 }

BOOLEAN CmpFindDrivers | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ControlSet,
|  | IN SERVICE_LOAD_TYPE | LoadType,
|  | IN PWSTR BootFileSystem | OPTIONAL,
|  | IN PLIST_ENTRY | DriverListHead
| ) |

Definition at line 333 of file cmboot.c.

References BOOT_DRIVER_NODE, CmpAddDriverToList(), CmpFindSubKeyByName(), CmpFindSubKeyByNumber(), CmpIsLoadType(), _BOOT_DRIVER_NODE::ErrorControl, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, Index, L, Name, PHCELL_INDEX, RtlAppendUnicodeToString(), RtlInitUnicodeString(), and TRUE.

Referenced by CmGetSystemDriverList().

    00343                    :
    00344
    00345     Traverses a particular control set and creates a list of boot drivers
    00346     to be loaded.  This list is unordered, but complete.
    00347
    00348 Arguments:
    00349
    00350     Hive - Supplies the hive control structure for the SYSTEM hive.
    00351
    00352     ControlSet - Supplies the HCELL_INDEX of the root of the control set.
    00353
    00354     LoadType - Supplies the type of drivers to be loaded (BootLoad,
    00355             SystemLoad, AutoLoad, etc)
    00356
    00357     BootFileSystem - If present, supplies the base name of the boot
    00358         filesystem, which is explicitly added to the driver list.
    00359
    00360     DriverListHead - Supplies a pointer to the head of the (empty) list
    00361             of boot drivers to load.
    00362
    00363 Return Value:
    00364
    00365     TRUE - List successfully created.
    00366
    00367     FALSE - Hive is corrupt.
    00368
    00369 --*/
    00370
    00371 {
    00372     HCELL_INDEX Services;
    00373     HCELL_INDEX Control;
    00374     HCELL_INDEX GroupOrder;
    00375     HCELL_INDEX DriverCell;
    00376     UNICODE_STRING Name;
    00377     PHCELL_INDEX Index;
    00378     int i;
    00379     UNICODE_STRING UnicodeString;
    00380     UNICODE_STRING BasePath;
    00381     WCHAR BaseBuffer[128];
    00382     PBOOT_DRIVER_NODE BootFileSystemNode;
    00383     PCM_KEY_NODE ControlNode;
    00384     PCM_KEY_NODE ServicesNode;
    00385
    00386     //
    00387     // Find SERVICES node.
    00388     //
    00389     ControlNode = (PCM_KEY_NODE)HvGetCell(Hive,ControlSet);
    00390     RtlInitUnicodeString(&Name, L"Services");
    00391     Services = CmpFindSubKeyByName(Hive,
    00392                                    ControlNode,
    00393                                    &Name);
    00394     if (Services == HCELL_NIL) {
    00395         return(FALSE);
    00396     }
    00397     ServicesNode = (PCM_KEY_NODE)HvGetCell(Hive,Services);
    00398
    00399     //
    00400     // Find CONTROL node.
    00401     //
    00402     RtlInitUnicodeString(&Name, L"Control");
    00403     Control = CmpFindSubKeyByName(Hive,
    00404                                   ControlNode,
    00405                                   &Name);
    00406     if (Control == HCELL_NIL) {
    00407         return(FALSE);
    00408     }
    00409
    00410     //
    00411     // Find GroupOrderList node.
    00412     //
    00413     RtlInitUnicodeString(&Name, L"GroupOrderList");
    00414     GroupOrder = CmpFindSubKeyByName(Hive,
    00415                                      (PCM_KEY_NODE)HvGetCell(Hive,Control),
    00416                                      &Name);
    00417     if (GroupOrder == HCELL_NIL) {
    00418         return(FALSE);
    00419     }
    00420
    00421     BasePath.Length = 0;
    00422     BasePath.MaximumLength = sizeof(BaseBuffer);
    00423     BasePath.Buffer = BaseBuffer;
    00424     RtlAppendUnicodeToString(&BasePath, L"\\Registry\\Machine\\System\\");
    00425     RtlAppendUnicodeToString(&BasePath, L"CurrentControlSet\\Services\\");
    00426
    00427     i=0;
    00428     do {
    00429         DriverCell = CmpFindSubKeyByNumber(Hive,ServicesNode,i++);
    00430         if (DriverCell != HCELL_NIL) {
    00431             if (CmpIsLoadType(Hive, DriverCell, LoadType)) {
    00432                 CmpAddDriverToList(Hive,
    00433                                    DriverCell,
    00434                                    GroupOrder,
    00435                                    &BasePath,
    00436                                    DriverListHead);
    00437
    00438             }
    00439         }
    00440     } while ( DriverCell != HCELL_NIL );
    00441
    00442     if (ARGUMENT_PRESENT(BootFileSystem)) {
    00443         //
    00444         // Add boot filesystem to boot driver list
    00445         //
    00446
    00447         RtlInitUnicodeString(&UnicodeString, BootFileSystem);
    00448         DriverCell = CmpFindSubKeyByName(Hive,
    00449                                          ServicesNode,
    00450                                          &UnicodeString);
    00451         if (DriverCell != HCELL_NIL) {
    00452             CmpAddDriverToList(Hive,
    00453                                DriverCell,
    00454                                GroupOrder,
    00455                                &BasePath,
    00456                                DriverListHead);
    00457
    00458             //
    00459             // mark the Boot Filesystem critical
    00460             //
    00461             BootFileSystemNode = CONTAINING_RECORD(DriverListHead->Flink,
    00462                                                    BOOT_DRIVER_NODE,
    00463                                                    ListEntry.Link);
    00464             BootFileSystemNode->ErrorControl = SERVICE_ERROR_CRITICAL;
    00465         }
    00466     }
    00467     return(TRUE);
    00468
    00469 }

HCELL_INDEX CmpFindNameInList | ( | IN PHHIVE | Hive,
|  | IN PCHILD_LIST | ChildList,
|  | IN PUNICODE_STRING | Name,
|  | IN OPTIONAL PCELL_DATA * | ChildAddress,
|  | IN OPTIONAL PULONG | ChildIndex
| ) |

Definition at line 33 of file cmtree.c.

References CmpCompareCompressedName(), _CM_KEY_VALUE::Flags, HCELL_NIL, Hive, HvGetCell, _CELL_DATA::_u::KeyList, List, Name, _CM_KEY_VALUE::Name, _CM_KEY_VALUE::NameLength, NTSTATUS(), RtlCompareUnicodeString(), TRUE, _CELL_DATA::u, and VALUE_COMP_NAME.

Referenced by CmDeleteValueKey(), CmpMergeKeyValues(), and CmSetValueKey().

    00042                    :
    00043
    00044     Find a child object in an object list.
    00045
    00046 Arguments:
    00047
    00048     Hive - pointer to hive control structure for hive of interest
    00049
    00050     List - pointer to mapped in list structure
    00051
    00052     Count - number of elements in list structure
    00053
    00054     Name - name of child object to find
    00055
    00056     ChildAddress - pointer to variable to receive address of mapped in child
    00057
    00058     ChildIndex - pointer to variable to receive index for child
    00059
    00060 Return Value:
    00061
    00062     HCELL_INDEX for the found cell
    00063     HCELL_NIL if not found
    00064
    00065 --*/
    00066 {
    00067     NTSTATUS    status;
    00068     ULONG   i;
    00069     PCM_KEY_VALUE pchild;
    00070     UNICODE_STRING Candidate;
    00071     BOOLEAN Success;
    00072     PCELL_DATA List;
    00073
    00074     if (ChildList->Count != 0) {
    00075         List = (PCELL_DATA)HvGetCell(Hive,ChildList->List);
    00076         for (i = 0; i < ChildList->Count; i++) {
    00077
    00078             pchild = (PCM_KEY_VALUE)HvGetCell(Hive, List->u.KeyList[i]);
    00079
    00080             if (pchild->Flags & VALUE_COMP_NAME) {
    00081                 Success = (CmpCompareCompressedName(Name,
    00082                                                     pchild->Name,
    00083                                                     pchild->NameLength)==0);
    00084             } else {
    00085                 Candidate.Length = pchild->NameLength;
    00086                 Candidate.MaximumLength = Candidate.Length;
    00087                 Candidate.Buffer = pchild->Name;
    00088                 Success = (RtlCompareUnicodeString(Name,
    00089                                                    &Candidate,
    00090                                                    TRUE)==0);
    00091             }
    00092
    00093             if (Success) {
    00094                 //
    00095                 // Success, return data to caller and exit
    00096                 //
    00097
    00098                 if (ARGUMENT_PRESENT(ChildIndex)) {
    00099                     *ChildIndex = i;
    00100                 }
    00101                 if (ARGUMENT_PRESENT(ChildAddress)) {
    00102                     *ChildAddress = (PCELL_DATA)pchild;
    00103                 }
    00104                 return(List->u.KeyList[i]);
    00105             }
    00106         }
    00107     }
    00108
    00109     return HCELL_NIL;
    00110 }

BOOLEAN CmpFindNLSData | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ControlSet,
|  | OUT PUNICODE_STRING | AnsiFilename,
|  | OUT PUNICODE_STRING | OemFilename,
|  | OUT PUNICODE_STRING | CaseTableFilename,
|  | OUT PUNICODE_STRING | OemHalFilename
| ) |

Definition at line 108 of file cmboot.c.

References CmpFindSubKeyByName(), CmpFindValueByName, CmpValueToData, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, Index, L, Name, NTSTATUS(), NULL, PHCELL_INDEX, RtlInitUnicodeString(), Status, TRUE, and USHORT.

    00119                    :
    00120
    00121     Traverses a particular control set and determines the filenames for
    00122     the NLS data files that need to be loaded.
    00123
    00124 Arguments:
    00125
    00126     Hive - Supplies the hive control structure for the SYSTEM hive.
    00127
    00128     ControlSet - Supplies the HCELL_INDEX of the root of the control set.
    00129
    00130     AnsiFileName - Returns the name of the Ansi codepage file (c_1252.nls)
    00131
    00132     OemFileName -  Returns the name of the OEM codepage file  (c_437.nls)
    00133
    00134     CaseTableFileName - Returns the name of the Unicode upper/lowercase
    00135             table for the language (l_intl.nls)
    00136
    00137     OemHalfont - Returns the name of the font file to be used by the HAL.
    00138
    00139 Return Value:
    00140
    00141     TRUE - filenames successfully determined
    00142
    00143     FALSE - hive is corrupt
    00144
    00145 --*/
    00146
    00147 {
    00148     UNICODE_STRING Name;
    00149     HCELL_INDEX Control;
    00150     HCELL_INDEX Nls;
    00151     HCELL_INDEX CodePage;
    00152     HCELL_INDEX Language;
    00153     HCELL_INDEX ValueCell;
    00154     PHCELL_INDEX Index;
    00155     PCM_KEY_VALUE Value;
    00156     NTSTATUS Status;
    00157     ULONG realsize;
    00158
    00159     //
    00160     // Find CONTROL node
    00161     //
    00162     RtlInitUnicodeString(&Name, L"Control");
    00163     Control = CmpFindSubKeyByName(Hive,
    00164                                  (PCM_KEY_NODE)HvGetCell(Hive,ControlSet),
    00165                                  &Name);
    00166     if (Control == HCELL_NIL) {
    00167         return(FALSE);
    00168     }
    00169
    00170     //
    00171     // Find NLS node
    00172     //
    00173     RtlInitUnicodeString(&Name, L"NLS");
    00174     Nls = CmpFindSubKeyByName(Hive,
    00175                              (PCM_KEY_NODE)HvGetCell(Hive,Control),
    00176                              &Name);
    00177     if (Nls == HCELL_NIL) {
    00178         return(FALSE);
    00179     }
    00180
    00181     //
    00182     // Find CodePage node
    00183     //
    00184     RtlInitUnicodeString(&Name, L"CodePage");
    00185     CodePage = CmpFindSubKeyByName(Hive,
    00186                                   (PCM_KEY_NODE)HvGetCell(Hive,Nls),
    00187                                   &Name);
    00188     if (CodePage == HCELL_NIL) {
    00189         return(FALSE);
    00190     }
    00191
    00192     //
    00193     // Find ACP value
    00194     //
    00195     RtlInitUnicodeString(&Name, L"ACP");
    00196     ValueCell = CmpFindValueByName(Hive,
    00197                                    (PCM_KEY_NODE)HvGetCell(Hive,CodePage),
    00198                                    &Name);
    00199     if (ValueCell == HCELL_NIL) {
    00200         return(FALSE);
    00201     }
    00202
    00203     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00204     Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize);
    00205     Name.MaximumLength=(USHORT)realsize;
    00206     Name.Length = 0;
    00207     while ((Name.Length<Name.MaximumLength) &&
    00208            (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
    00209         Name.Length += sizeof(WCHAR);
    00210     }
    00211
    00212     //
    00213     // Find ACP filename
    00214     //
    00215     ValueCell = CmpFindValueByName(Hive,
    00216                                    (PCM_KEY_NODE)HvGetCell(Hive,CodePage),
    00217                                    &Name);
    00218     if (ValueCell == HCELL_NIL) {
    00219         return(FALSE);
    00220     }
    00221
    00222     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00223     AnsiFilename->Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize);
    00224     AnsiFilename->Length = AnsiFilename->MaximumLength = (USHORT)realsize;
    00225
    00226     //
    00227     // Find OEMCP node
    00228     //
    00229     RtlInitUnicodeString(&Name, L"OEMCP");
    00230     ValueCell = CmpFindValueByName(Hive,
    00231                                    (PCM_KEY_NODE)HvGetCell(Hive,CodePage),
    00232                                    &Name);
    00233     if (ValueCell == HCELL_NIL) {
    00234         return(FALSE);
    00235     }
    00236
    00237     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00238     Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize);
    00239     Name.MaximumLength = (USHORT)realsize;
    00240     Name.Length = 0;
    00241     while ((Name.Length<Name.MaximumLength) &&
    00242            (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
    00243         Name.Length += sizeof(WCHAR);
    00244     }
    00245
    00246     //
    00247     // Find OEMCP filename
    00248     //
    00249     ValueCell = CmpFindValueByName(Hive,
    00250                                    (PCM_KEY_NODE)HvGetCell(Hive,CodePage),
    00251                                    &Name);
    00252     if (ValueCell == HCELL_NIL) {
    00253         return(FALSE);
    00254     }
    00255
    00256     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00257     OemFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize);
    00258     OemFilename->Length = OemFilename->MaximumLength = (USHORT)realsize;
    00259
    00260     //
    00261     // Find Language node
    00262     //
    00263     RtlInitUnicodeString(&Name, L"Language");
    00264     Language = CmpFindSubKeyByName(Hive,
    00265                                    (PCM_KEY_NODE)HvGetCell(Hive,Nls),
    00266                                    &Name);
    00267     if (Language == HCELL_NIL) {
    00268         return(FALSE);
    00269     }
    00270
    00271     //
    00272     // Find Default value
    00273     //
    00274     RtlInitUnicodeString(&Name, L"Default");
    00275     ValueCell = CmpFindValueByName(Hive,
    00276                                    (PCM_KEY_NODE)HvGetCell(Hive,Language),
    00277                                    &Name);
    00278     if (ValueCell == HCELL_NIL) {
    00279             return(FALSE);
    00280     }
    00281
    00282     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00283     Name.Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize);
    00284     Name.MaximumLength = (USHORT)realsize;
    00285     Name.Length = 0;
    00286
    00287     while ((Name.Length<Name.MaximumLength) &&
    00288            (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
    00289         Name.Length+=sizeof(WCHAR);
    00290     }
    00291
    00292     //
    00293     // Find default filename
    00294     //
    00295     ValueCell = CmpFindValueByName(Hive,
    00296                                    (PCM_KEY_NODE)HvGetCell(Hive,Language),
    00297                                    &Name);
    00298     if (ValueCell == HCELL_NIL) {
    00299         return(FALSE);
    00300     }
    00301
    00302     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00303     CaseTableFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize);
    00304     CaseTableFilename->Length = CaseTableFilename->MaximumLength = (USHORT)realsize;
    00305
    00306     //
    00307     // Find OEMHAL filename
    00308     //
    00309     RtlInitUnicodeString(&Name, L"OEMHAL");
    00310     ValueCell = CmpFindValueByName(Hive,
    00311                                    (PCM_KEY_NODE)HvGetCell(Hive,CodePage),
    00312                                    &Name);
    00313     if (ValueCell == HCELL_NIL) {
    00314 #ifdef i386
    00315         OemHalFont->Buffer = NULL;
    00316         OemHalFont->Length = 0;
    00317         OemHalFont->MaximumLength = 0;
    00318         return TRUE;
    00319 #endif
    00320         return(FALSE);
    00321     }
    00322
    00323     Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    00324     OemHalFont->Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize);
    00325     OemHalFont->Length = (USHORT)realsize;
    00326     OemHalFont->MaximumLength = (USHORT)realsize;
    00327
    00328     return(TRUE);
    00329 }

HCELL_INDEX CmpFindProfileOption | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ControlSet,
|  | OUT PCM_HARDWARE_PROFILE_LIST * | ProfileList,
|  | OUT PCM_HARDWARE_PROFILE_ALIAS_LIST * | AliasList,
|  | OUT PULONG | Timeout
| ) |

| Referenced by CmpSetCurrentProfile().

HCELL_INDEX CmpFindSubKeyByName | ( | PHHIVE | Hive,
|  | PCM_KEY_NODE | Parent,
|  | PUNICODE_STRING | SearchName
| ) |

Definition at line 186 of file cmindex.c.

References ASSERT, CM_KEY_FAST_LEAF, CM_KEY_INDEX_LEAF, CM_KEY_INDEX_ROOT, CML_MAJOR, CMLOG, CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), CmpHintHits, CmpHintMisses, CMS_INDEX, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, HvIsCellAllocated(), _CM_KEY_INDEX::Signature, _HHIVE::StorageTypeCount, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, and _CM_KEY_NODE::WorkVar.

Referenced by CmGetSystemControlValues(), CmpCopySyncTree2(), CmpFindControlSet(), CmpFindDrivers(), CmpFindNLSData(), CmpFindProfileOption(), CmpParseKey(), CmpSortDriverList(), CmpSyncSubKeysAfterDelete(), and CmpWalkPath().

    00193                    :
    00194
    00195     Find the child cell (either subkey or value) specified by name.
    00196
    00197 Arguments:
    00198
    00199     Hive - pointer to hive control structure for hive of interest
    00200
    00201     Parent - cell of key body which is parent of child of interest
    00202
    00203     SearchName - name of child of interest
    00204
    00205 Return Value:
    00206
    00207     Cell of matching child key, or HCELL_NIL if none.
    00208
    00209 --*/
    00210 {
    00211     PCM_KEY_INDEX   IndexRoot;
    00212     HCELL_INDEX     Child;
    00213     ULONG           i;
    00214     ULONG           FoundIndex;
    00215
    00216     CMLOG(CML_MAJOR, CMS_INDEX) {
    00217         KdPrint(("CmpFindSubKeyByName:\n\t"));
    00218         KdPrint(("Hive=%08lx Parent=%08lx SearchName=%08lx\n", Hive, Parent, SearchName));
    00219     }
    00220
    00221     //
    00222     // Try first the Stable, then the Volatile store.  Assumes that
    00223     // all Volatile refs in Stable space are zeroed out at boot.
    00224     //
    00225     for (i = 0; i < Hive->StorageTypeCount; i++) {
    00226         if (Parent->SubKeyCounts[i] != 0) {
    00227             ASSERT(HvIsCellAllocated(Hive, Parent->SubKeyLists[i]));
    00228             IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
    00229
    00230             if (IndexRoot->Signature == CM_KEY_INDEX_ROOT) {
    00231                 CmpFindSubKeyInRoot(Hive, IndexRoot, SearchName, &Child);
    00232                 if (Child == HCELL_NIL) {
    00233                     continue;
    00234                 }
    00235                 IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
    00236             }
    00237             ASSERT((IndexRoot->Signature == CM_KEY_INDEX_LEAF) ||
    00238                    (IndexRoot->Signature == CM_KEY_FAST_LEAF));
    00239
    00240             FoundIndex = CmpFindSubKeyInLeaf(Hive,
    00241                                              IndexRoot,
    00242                                              Parent->WorkVar,
    00243                                              SearchName,
    00244                                              &Child);
    00245             if (Child != HCELL_NIL) {
    00246                 //
    00247                 // WorkVar is used as a hint for the last successful lookup
    00248                 // to improve our locality when similar keys are opened
    00249                 // repeatedly.
    00250                 //
    00251                 if (FoundIndex == Parent->WorkVar) {
    00252                     CmpHintHits++;
    00253                 } else {
    00254                     CmpHintMisses++;
    00255                 }
    00256                 Parent->WorkVar = FoundIndex;
    00257                 return Child;
    00258             }
    00259         }
    00260     }
    00261     return HCELL_NIL;
    00262 }

HCELL_INDEX CmpFindSubKeyByNumber | ( | PHHIVE | Hive,
|  | PCM_KEY_NODE | Parent,
|  | ULONG | Number
| ) |

Definition at line 771 of file cmindex.c.

References CML_MAJOR, CMLOG, CmpDoFindSubKeyByNumber(), CMS_INDEX, HCELL_NIL, Hive, HvGetCell, Index, Stable, _HHIVE::StorageTypeCount, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, and Volatile.

Referenced by CmEnumerateKey(), CmpCheckRegistry2(), CmpCopySyncTree2(), CmpDeleteTree(), CmpFindDrivers(), CmpFindMatchingDescriptorCell(), CmpFindProfileOption(), and CmpSyncSubKeysAfterDelete().

    00778                    :
    00779
    00780     Find the Number'th entry in the index, starting from 0.
    00781
    00782 Arguments:
    00783
    00784     Hive - pointer to hive control structure for hive of interest
    00785
    00786     Node - pointer to key body which is parent of child of interest
    00787
    00788     Number - ordinal of child key to return
    00789
    00790 Return Value:
    00791
    00792     Cell of matching child key, or HCELL_NIL if none.
    00793
    00794 --*/
    00795 {
    00796     PCM_KEY_INDEX   Index;
    00797
    00798     CMLOG(CML_MAJOR, CMS_INDEX) {
    00799         KdPrint(("CmpFindSubKeyByNumber:\n\t"));
    00800         KdPrint(("Hive=%08lx Node=%08lx Number=%08lx\n",Hive,Node,Number));
    00801     }
    00802
    00803     if (Number < Node->SubKeyCounts[Stable]) {
    00804
    00805         //
    00806         // It's in the stable set
    00807         //
    00808         Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Stable]);
    00809         return (CmpDoFindSubKeyByNumber(Hive, Index, Number));
    00810
    00811     } else if (Hive->StorageTypeCount > Volatile) {
    00812
    00813         //
    00814         // It's in the volatile set
    00815         //
    00816         Number = Number - Node->SubKeyCounts[Stable];
    00817         if (Number < Node->SubKeyCounts[Volatile]) {
    00818
    00819             Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Volatile]);
    00820             return (CmpDoFindSubKeyByNumber(Hive, Index, Number));
    00821
    00822         }
    00823     }
    00824
    00825     //
    00826     // It's nowhere
    00827     //
    00828     return HCELL_NIL;
    00829 }

HCELL_INDEX CmpFindValueByName | ( | PHHIVE | Hive,
|  | PCM_KEY_NODE | KeyNode,
|  | PUNICODE_STRING | Name
| ) |

PCM_KEY_VALUE CmpFindValueByNameFromCache | ( | IN PHHIVE | Hive,
|  | IN PCACHED_CHILD_LIST | ChildList,
|  | IN PUNICODE_STRING | Name,
|  | OUT PPCM_CACHED_VALUE * | ContainingList,
|  | OUT ULONG * | Index,
|  | OUT BOOLEAN * | ValueCached
| ) |

Definition at line 309 of file cmtree.c.

References CmpCompareCompressedName(), CmpGetValueKeyFromCache(), CmpGetValueListFromCache(), _CM_KEY_VALUE::Flags, Hive, Index, List, Name, _CM_KEY_VALUE::Name, _CM_KEY_VALUE::NameLength, NTSTATUS(), NULL, RtlCompareUnicodeString(), TRUE, and VALUE_COMP_NAME.

Referenced by CmQueryValueKey().

    00319                    :
    00320
    00321     Find a value node given a value list array and a value name.  It sequentially walk
    00322     through each value node to look for a match.  If the array and
    00323     value nodes touched are not already cached, cache them.
    00324
    00325 Arguments:
    00326
    00327     Hive - pointer to hive control structure for hive of interest
    00328
    00329     ChildList - pointer/index to the Value Index array
    00330
    00331     Name - name of value to find
    00332
    00333     ContainlingList - The address of the entry that will receive the found cached value.
    00334
    00335     Index - pointer to variable to receive index for child
    00336
    00337     ValueCached - Indicate if the value node is cached.
    00338
    00339 Return Value:
    00340
    00341     HCELL_INDEX for the found cell
    00342     HCELL_NIL if not found
    00343
    00344 --*/
    00345 {
    00346     NTSTATUS    status;
    00347     ULONG   i;
    00348     PCM_KEY_VALUE pchild;
    00349     UNICODE_STRING Candidate;
    00350     BOOLEAN Success;
    00351     PCELL_DATA List;
    00352     BOOLEAN IndexCached;
    00353
    00354     if (ChildList->Count != 0) {
    00355         List = CmpGetValueListFromCache(Hive, ChildList, &IndexCached);
    00356
    00357         for (i = 0; i < ChildList->Count; i++) {
    00358             pchild = CmpGetValueKeyFromCache(Hive, List, i, ContainingList, IndexCached, ValueCached);
    00359
    00360             if (pchild->Flags & VALUE_COMP_NAME) {
    00361                 Success = (CmpCompareCompressedName(Name,
    00362                                                     pchild->Name,
    00363                                                     pchild->NameLength)==0);
    00364             } else {
    00365                 Candidate.Length = pchild->NameLength;
    00366                 Candidate.MaximumLength = Candidate.Length;
    00367                 Candidate.Buffer = pchild->Name;
    00368                 Success = (RtlCompareUnicodeString(Name,
    00369                                                    &Candidate,
    00370                                                    TRUE)==0);
    00371             }
    00372
    00373             if (Success) {
    00374                 //
    00375                 // Success, fill the index, return data to caller and exit
    00376                 //
    00377                 *Index = i;
    00378                 return(pchild);
    00379             }
    00380         }
    00381     }
    00382
    00383     return NULL;
    00384 }

VOID CmpFlushNotify | ( | PCM_KEY_BODY | KeyBody | ) |

Definition at line 1235 of file cmnotify.c.

References ASSERT, ASSERT_CM_LOCK_OWNED, CML_MAJOR, CmLockHive, CMLOG, CmpClearListEntry, CmpInitializeKeyNameString(), CmpPostNotify(), CMS_NOTIFY, CmUnlockHive, DbgPrint, _CM_KEY_CONTROL_BLOCK::Delete, ExAllocatePool, ExFreePool(), FALSE, Hive, HiveList, _CM_NOTIFY_BLOCK::HiveList, _CM_KEY_BODY::KeyControlBlock, _CM_KEY_CONTROL_BLOCK::KeyHive, KeyName, _CM_KEY_CONTROL_BLOCK::KeyNode, MAX_KEY_NAME_LENGTH, _CM_KEY_BODY::NotifyBlock, NULL, PAGED_CODE, PagedPool, _CM_NOTIFY_BLOCK::PostList, SeReleaseSubjectContext(), and _CM_NOTIFY_BLOCK::SubjectContext.

Referenced by CmDeleteKey(), CmpDeleteKeyObject(), CmpRefreshHive(), and NtUnloadKey().

    01240                    :
    01241
    01242     Clean up notifyblock when a handle is closed or the key it refers
    01243     to is deleted.
    01244
    01245 Arguments:
    01246
    01247     KeyBody - supplies pointer to key object body for handle we
    01248                 are cleaning up.
    01249
    01250 Return Value:
    01251
    01252     NONE
    01253
    01254 --*/
    01255 {
    01256     PCM_NOTIFY_BLOCK    NotifyBlock;
    01257     PCMHIVE             Hive;
    01258
    01259     PAGED_CODE();
    01260     ASSERT_CM_LOCK_OWNED();
    01261
    01262     if (KeyBody->NotifyBlock == NULL) {
    01263         return;
    01264     }
    01265
    01266 #ifdef KCB_TO_KEYBODY_LINK
    01267     ASSERT( KeyBody->KeyControlBlock->Delete == FALSE );
    01268 #endif
    01269
    01270     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    01271 #if DBG
    01272         WCHAR                   *NameBuffer = NULL;
    01273         UNICODE_STRING          KeyName;
    01274
    01275         KdPrint(("[CM]CmpFlushNotify: NotifyBlock = %08lx\n",KeyBody->NotifyBlock));
    01276         NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    01277         if(NameBuffer && KeyBody->KeyControlBlock->KeyNode) {
    01278            CmpInitializeKeyNameString(KeyBody->KeyControlBlock->KeyNode,&KeyName,NameBuffer);
    01279            KdPrint(("\t[CM]CmpFlushNotify: Key = %.*S\n",KeyName.Length / sizeof(WCHAR),KeyName.Buffer));
    01280            ExFreePool(NameBuffer);
    01281         }
    01282 #endif
    01283     }
    01284
    01285     //
    01286     // Lock the hive exclusively to prevent multiple threads from whacking
    01287     // on the list.
    01288     //
    01289     Hive = CONTAINING_RECORD(KeyBody->KeyControlBlock->KeyHive,
    01290                              CMHIVE,
    01291                              Hive);
    01292     CmLockHive(Hive);
    01293     //
    01294     // Reread the notify block in case it has already been freed.
    01295     //
    01296     NotifyBlock = KeyBody->NotifyBlock;
    01297     if (NotifyBlock == NULL) {
    01298         CmUnlockHive(Hive);
    01299         return;
    01300     }
    01301
    01302     //
    01303     // Clean up all PostBlocks waiting on the NotifyBlock
    01304     //
    01305     if (IsListEmpty(&(NotifyBlock->PostList)) == FALSE) {
    01306         CmpPostNotify(
    01307             NotifyBlock,
    01308             NULL,
    01309             0,
    01310             STATUS_NOTIFY_CLEANUP,
    01311             NULL
    01312             );
    01313     }
    01314
    01315     //
    01316     // Release the subject context
    01317     //
    01318     SeReleaseSubjectContext(&NotifyBlock->SubjectContext);
    01319
    01320     //
    01321     // IMPLEMENTATION NOTE:
    01322     //      If we ever do code to report names and types of events,
    01323     //      this is the place to free the buffer.
    01324     //
    01325
    01326     //
    01327     // Remove the NotifyBlock from the hive chain
    01328     //
    01329     NotifyBlock->HiveList.Blink->Flink = NotifyBlock->HiveList.Flink;
    01330     if (NotifyBlock->HiveList.Flink != NULL) {
    01331         NotifyBlock->HiveList.Flink->Blink = NotifyBlock->HiveList.Blink;
    01332     }
    01333
    01334     // Protect for multiple deletion of the same object
    01335     CmpClearListEntry(&(NotifyBlock->HiveList));
    01336
    01337     KeyBody->NotifyBlock = NULL;
    01338
    01339 #ifdef _CM_ENTRYLIST_MANIPULATION
    01340     if (IsListEmpty(&(NotifyBlock->PostList)) == FALSE) {
    01341         DbgPrint("CmpFlushNotify: NotifyBlock %08lx\n",NotifyBlock);
    01342         DbgBreakPoint();
    01343     }
    01344     //check is the notify has been deleted from the hive notify list
    01345     {
    01346         PCM_NOTIFY_BLOCK ValidNotifyBlock;
    01347         PLIST_ENTRY NotifyPtr;
    01348
    01349         NotifyPtr = &(Hive->NotifyList);
    01350
    01351         while (NotifyPtr->Flink != NULL) {
    01352             NotifyPtr = NotifyPtr->Flink;
    01353
    01354             ValidNotifyBlock = CONTAINING_RECORD(NotifyPtr, CM_NOTIFY_BLOCK, HiveList);
    01355             if( ValidNotifyBlock == NotifyBlock ) {
    01356                 DbgPrint("CmpFlushNotify: NotifyBlock %08lx is about to be deleted but is still in the hive notify list\n",NotifyBlock);
    01357                 DbgBreakPoint();
    01358             }
    01359         }
    01360     }
    01361     RtlZeroMemory((PVOID)NotifyBlock, sizeof(CM_NOTIFY_BLOCK));
    01362 #endif
    01363
    01364     CmUnlockHive(Hive);
    01365
    01366     //
    01367     // Free the block, clean up the KeyBody
    01368     //
    01369     ExFreePool(NotifyBlock);
    01370     return;
    01371 }

VOID CmpFree | ( | PVOID | MemoryBlock,
|  | ULONG | GlobalQuotaSize
| ) |

Definition at line 186 of file cmwrapr.c.

References ASSERT, CML_MINOR, CMLOG, CmpReleaseGlobalQuota(), CMS_POOL, ExFreePool(), and RtlGetCallersAddress().

Referenced by CmpDestroyTemporaryHive(), CmpInitializeHive(), CmpValidateAlternate(), CmReplaceKey(), CmUnloadKey(), EhCloseHive(), HvFreeHive(), HvFreeHivePartial(), and HvWriteHive().

    00192                    :
    00193
    00194     This routine frees memory that has been allocated by the registry.
    00195
    00196     It is environment specific
    00197
    00198
    00199 Arguments:
    00200
    00201     MemoryBlock - supplies address of memory object to free
    00202
    00203     GlobalQuotaSize - amount of global quota to release
    00204
    00205 Return Value:
    00206
    00207     NONE
    00208
    00209 --*/
    00210 {
    00211 #if DBG
    00212     PVOID   Caller;
    00213     PVOID   CallerCaller;
    00214     RtlGetCallersAddress(&Caller, &CallerCaller);
    00215     CMLOG(CML_MINOR, CMS_POOL) {
    00216         KdPrint(("**FREEING:%08lx c,cc:%08lx,%08lx\n", MemoryBlock, Caller, CallerCaller));
    00217     }
    00218 #endif
    00219     ASSERT(GlobalQuotaSize > 0);
    00220     CmpReleaseGlobalQuota(GlobalQuotaSize);
    00221     ExFreePool(MemoryBlock);
    00222     return;
    00223 }

VOID CmpFreeKeyBody | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 1297 of file cmsubs.c.

References Cell, _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, _CM_KEY_NODE::Flags, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, KEY_HIVE_EXIT, _CELL_DATA::_u::KeyNode, _CM_KEY_NODE::Security, and _CELL_DATA::u.

Referenced by CmpFreeKeyByCell().

    01303                    :
    01304
    01305     Free storage for the key entry Hive.Cell refers to, including
    01306     its class and security data.  Will NOT free child list or value list.
    01307
    01308 Arguments:
    01309
    01310     Hive - supplies a pointer to the hive control structure for the hive
    01311
    01312     Cell - supplies index of key to free
    01313
    01314 Return Value:
    01315
    01316     NTSTATUS - Result code from call, among the following:
    01317
    01318         <TBS>
    01319
    01320 --*/
    01321 {
    01322     PCELL_DATA key;
    01323
    01324     //
    01325     // map in the cell
    01326     //
    01327     key = HvGetCell(Hive, Cell);
    01328
    01329     if (!(key->u.KeyNode.Flags & KEY_HIVE_EXIT)) {
    01330         if (key->u.KeyNode.Security != HCELL_NIL) {
    01331             HvFreeCell(Hive, key->u.KeyNode.Security);
    01332         }
    01333
    01334         if (key->u.KeyNode.ClassLength > 0) {
    01335             HvFreeCell(Hive, key->u.KeyNode.Class);
    01336         }
    01337     }
    01338
    01339     //
    01340     // unmap the cell itself and free it
    01341     //
    01342     HvFreeCell(Hive, Cell);
    01343
    01344     return;
    01345 }

NTSTATUS CmpFreeKeyByCell | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | BOOLEAN | Unlink
| ) |

Definition at line 140 of file cmtredel.c.

References ASSERT, Cell, CmpFreeKeyBody(), CmpFreeSecurityDescriptor(), CmpFreeValue(), CmpMarkKeyDirty(), CmpRemoveSubKey(), _CHILD_LIST::Count, _CM_KEY_NODE::Flags, Hive, HvFreeCell(), HvGetCell, KEY_HIVE_EXIT, KEY_PREDEF_HANDLE, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyNode, _CHILD_LIST::List, _CM_KEY_NODE::MaxClassLen, _CM_KEY_NODE::MaxNameLen, _CM_KEY_NODE::Parent, Stable, _CM_KEY_NODE::SubKeyCounts, TRUE, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmDeleteKey(), CmpDeleteTree(), CmpDestroyHive(), CmpDoCreate(), CmpSyncSubKeysAfterDelete(), CmRestoreKey(), and EhCreateChild().

    00147                    :
    00148
    00149     Actually free the storage for the specified cell.  We will first
    00150     remove it from its parent's child key list, then free all of its
    00151     values, then the key body itself.
    00152
    00153 Arguments:
    00154
    00155     Hive - pointer to hive control structure for hive of interest
    00156
    00157     Cell - index for cell to free storage for (the target)
    00158
    00159     Unlink - if TRUE, target cell will be removed from parent cell's
    00160              subkeylist, if FALSE, it will NOT be.
    00161
    00162 Return Value:
    00163
    00164     NONE.
    00165
    00166 --*/
    00167 {
    00168     PCELL_DATA  ptarget;
    00169     PCELL_DATA  pparent;
    00170     PCELL_DATA  plist;
    00171     ULONG       i;
    00172
    00173     //
    00174     // Mark dirty everything that we might touch
    00175     //
    00176     if (! CmpMarkKeyDirty(Hive, Cell)) {
    00177         return STATUS_NO_LOG_SPACE;
    00178     }
    00179
    00180     //
    00181     // Map in the target
    00182     //
    00183     ptarget = HvGetCell(Hive, Cell);
    00184     ASSERT((ptarget->u.KeyNode.SubKeyCounts[Stable] +
    00185             ptarget->u.KeyNode.SubKeyCounts[Volatile]) == 0);
    00186
    00187
    00188     if (Unlink == TRUE) {
    00189         BOOLEAN Success;
    00190
    00191         Success = CmpRemoveSubKey(Hive, ptarget->u.KeyNode.Parent, Cell);
    00192         if (!Success) {
    00193             return STATUS_INSUFFICIENT_RESOURCES;
    00194         }
    00195         pparent = HvGetCell(Hive, ptarget->u.KeyNode.Parent);
    00196         if ( (pparent->u.KeyNode.SubKeyCounts[Stable] +
    00197               pparent->u.KeyNode.SubKeyCounts[Volatile]) == 0)
    00198         {
    00199             pparent->u.KeyNode.MaxNameLen = 0;
    00200             pparent->u.KeyNode.MaxClassLen = 0;
    00201         }
    00202     }
    00203
    00204     //
    00205     // Target is now an unreferenced key, free it's actual storage
    00206     //
    00207
    00208     //
    00209     // Free misc stuff
    00210     //
    00211     if (!(ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) &&
    00212         !(ptarget->u.KeyNode.Flags & KEY_PREDEF_HANDLE) ) {
    00213
    00214         //
    00215         // First, free the value entries
    00216         //
    00217         if (ptarget->u.KeyNode.ValueList.Count > 0) {
    00218
    00219             // target list
    00220             plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
    00221
    00222             for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
    00223                 CmpFreeValue(Hive, plist->u.KeyList[i]);
    00224             }
    00225
    00226             HvFreeCell(Hive, ptarget->u.KeyNode.ValueList.List);
    00227         }
    00228
    00229         //
    00230         // Free the security descriptor
    00231         //
    00232         CmpFreeSecurityDescriptor(Hive, Cell);
    00233     }
    00234
    00235     //
    00236     // Free the key body itself, and Class data.
    00237     //
    00238     CmpFreeKeyBody(Hive, Cell);
    00239
    00240     return STATUS_SUCCESS;
    00241 }

VOID CmpFreePostBlock | ( | IN PCM_POST_BLOCK | PostBlock | ) |

Definition at line 3764 of file ntapi.c.

References ASSERT, CM_POST_BLOCK, CML_API, CML_MAJOR, CMLOG, CmpClearListEntry, CmpInitializeKeyNameString(), CMS_NOTIFY, CMS_NTAPI, DbgPrint, ExAllocatePool, ExFreePool(), IsMasterPostBlock, KeyName, MAX_KEY_NAME_LENGTH, NULL, ObDereferenceObject, PagedPool, PostAsyncKernel, PostAsyncUser, PostBlockType, PostSynchronous, and REG_NOTIFY_MASTER_POST.

Referenced by CmNotifyRunDown(), CmpFreeSlavePost(), CmpNotifyChangeKey(), CmpPostApc(), CmpPostApcRunDown(), CmpPostNotify(), and NtNotifyChangeMultipleKeys().

    03770                    :
    03771
    03772     Frees the various bits of pool that were allocated for a postblock
    03773
    03774 Arguments:
    03775
    03776     None
    03777
    03778 Return Value:
    03779
    03780     None.
    03781
    03782 --*/
    03783
    03784 {
    03785
    03786     CMLOG(CML_API, CMS_NTAPI) {
    03787 #if DBG
    03788         if(PostBlock->TraceIntoDebugger) {
    03789             KdPrint(("[CM]CmpFreePostBlock: PostBlock:%08lx\t", PostBlock));
    03790             if( PostBlock->NotifyType&REG_NOTIFY_MASTER_POST) {
    03791                 KdPrint(("--MasterBlock\n"));
    03792             } else {
    03793                 KdPrint(("--SlaveBlock\n"));
    03794             }
    03795         }
    03796 #endif
    03797     }
    03798
    03799 #ifdef _CM_ENTRYLIST_MANIPULATION
    03800     // check if the post block has been removed from the notify and thread list(s)
    03801     if((PostBlock->NotifyList.Flink != NULL) || (PostBlock->NotifyList.Blink != NULL)) {
    03802         DbgPrint("CmpFreePostBlock: Attempt to free post block %08lx not removed from notify list\n",PostBlock);
    03803         DbgBreakPoint();
    03804     }
    03805     if((PostBlock->ThreadList.Flink != NULL) || (PostBlock->ThreadList.Blink != NULL)) {
    03806         DbgPrint("CmpFreePostBlock: Attempt to free post block %08lx not removed from thread list\n",PostBlock);
    03807         DbgBreakPoint();
    03808     }
    03809
    03810 #endif
    03811
    03812     // Protect for multiple deletion of the same object
    03813     CmpClearListEntry(&(PostBlock->CancelPostList));
    03814
    03815     //
    03816     // Cleanup for objects referenced by NtNotifyMultipleKeys
    03817     //
    03818     if( PostBlock->PostKeyBody) {
    03819
    03820         //
    03821         // If we have a PostKeyBody, the attached key body must not be NULL
    03822         //
    03823         ASSERT(PostBlock->PostKeyBody->KeyBody);
    03824
    03825         CMLOG(CML_MAJOR, CMS_NOTIFY) {
    03826 #if DBG
    03827             WCHAR                   *NameBuffer = NULL;
    03828             UNICODE_STRING          KeyName;
    03829
    03830             KdPrint(("[CM]\tCmpFreePostBlock: Dereferencing KeyBody:%08lx\n", PostBlock->PostKeyBody->KeyBody));
    03831             NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    03832             if(NameBuffer) {
    03833                CmpInitializeKeyNameString(PostBlock->PostKeyBody->KeyBody->KeyControlBlock->KeyNode,&KeyName,NameBuffer);
    03834                KdPrint(("[CM]\tCmpFreePostBlock: KeyName:tKey = %.*S\n",KeyName.Length / sizeof(WCHAR),KeyName.Buffer));
    03835                ExFreePool(NameBuffer);
    03836             }
    03837 #endif
    03838         }
    03839
    03840         //
    03841         // KeyBodyList must be used only in CmpPostBlock implementation for the delayed dereferencing mechanism.
    03842         //
    03843         ASSERT(IsListEmpty(&(PostBlock->PostKeyBody->KeyBodyList)));
    03844
    03845         //
    03846         // dereference the actual keybody
    03847         //
    03848         ObDereferenceObject(PostBlock->PostKeyBody->KeyBody);
    03849
    03850         //
    03851         // Free the PostKeyBody structure
    03852         //
    03853         ExFreePool(PostBlock->PostKeyBody);
    03854     }
    03855
    03856     if( IsMasterPostBlock(PostBlock) ) {
    03857         //
    03858         // this members are allocated only for master post blocks
    03859         //
    03860         switch (PostBlockType(PostBlock)) {
    03861             case PostSynchronous:
    03862                 ExFreePool(PostBlock->u->Sync.SystemEvent);
    03863                 break;
    03864             case PostAsyncUser:
    03865                 ExFreePool(PostBlock->u->AsyncUser.Apc);
    03866                 break;
    03867             case PostAsyncKernel:
    03868                 break;
    03869         }
    03870         ExFreePool(PostBlock->u);
    03871     }
    03872
    03873 #ifdef _CM_ENTRYLIST_MANIPULATION
    03874     RtlZeroMemory((PVOID)PostBlock, sizeof(CM_POST_BLOCK));
    03875 #endif
    03876
    03877     // and the storage for the Post object
    03878     ExFreePool(PostBlock);
    03879 }

VOID CmpFreeSecurityDescriptor | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell
| ) |

Definition at line 1464 of file cmse.c.

Referenced by CmpFreeKeyByCell(), and CmpFreeKeyValues().

    01471                    :
    01472
    01473     Frees the security descriptor associated with a particular node.  This
    01474     can only happen when the node is actually being deleted from the
    01475     registry.
    01476
    01477     NOTE:   Caller is expected to have already marked relevent cells dirty.
    01478
    01479 Arguments:
    01480
    01481     Hive - Supplies thepointer to hive control structure for hive of interest
    01482
    01483     Cell - Supplies index for cell to free storage for (the target)
    01484
    01485 Return Value:
    01486
    01487     None.
    01488
    01489 --*/
    01490
    01491 {
    01492     PCELL_DATA Node;
    01493     PCELL_DATA Security;
    01494     HCELL_INDEX SecurityCell;
    01495
    01496     PAGED_CODE();
    01497     CMLOG(CML_FLOW, CMS_SEC) {
    01498         KdPrint(("CmpFreeSecurityDescriptor for cell %ld\n",Cell));
    01499     }
    01500
    01501     //
    01502     // Map in the cell whose security descriptor is being freed
    01503     //
    01504     Node = HvGetCell(Hive, Cell);
    01505     ASSERT_NODE(&(Node->u.KeyNode));
    01506
    01507     //
    01508     // Map in the cell containing the security descriptor.
    01509     //
    01510     SecurityCell = Node->u.KeyNode.Security;
    01511     Security = HvGetCell(Hive, SecurityCell);
    01512     ASSERT_SECURITY(&(Security->u.KeySecurity));
    01513
    01514
    01515     if (Security->u.KeySecurity.ReferenceCount == 1) {
    01516
    01517         //
    01518         // This is the only cell that references this security descriptor,
    01519         // so it is ok to free it now.
    01520         //
    01521         CmpRemoveSecurityCellList(Hive, SecurityCell);
    01522         HvFreeCell(Hive, SecurityCell);
    01523         CMLOG(CML_FLOW, CMS_SEC) {
    01524             KdPrint(("CmpFreeSecurityDescriptor: freeing security cell\n"));
    01525         }
    01526     } else {
    01527
    01528         //
    01529         // More than one node references this security descriptor, so
    01530         // just decrement the reference count.
    01531         //
    01532         Security->u.KeySecurity.ReferenceCount -= 1;
    01533         CMLOG(CML_FLOW, CMS_SEC) {
    01534             KdPrint(("CmpFreeSecurityDescriptor: decrementing reference count\n"));
    01535         }
    01536     }
    01537
    01538     //
    01539     // Zero out the pointer to the security descriptdr in the main cell
    01540     //
    01541     Node->u.KeyNode.Security = HCELL_NIL;
    01542 }

VOID CmpFreeValue | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 53 of file cmsubs2.c.

References Cell, CmpIsHKeyValueSmall, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, Hive, HvFreeCell(), HvGetCell, _CELL_DATA::_u::KeyValue, and _CELL_DATA::u.

Referenced by CmDeleteValueKey(), CmpFreeKeyByCell(), and CmpFreeKeyValues().

    00059                    :
    00060
    00061     Free the value entry Hive.Cell refers to, including
    00062     its name and data cells.
    00063
    00064 Arguments:
    00065
    00066     Hive - supplies a pointer to the hive control structure for the hive
    00067
    00068     Cell - supplies index of value to delete
    00069
    00070 Return Value:
    00071
    00072     NTSTATUS - Result code from call, among the following:
    00073
    00074         <TBS>
    00075
    00076 --*/
    00077 {
    00078     PCELL_DATA value;
    00079     ULONG       realsize;
    00080     BOOLEAN     small;
    00081
    00082     //
    00083     // map in the cell
    00084     //
    00085     value = HvGetCell(Hive, Cell);
    00086
    00087     //
    00088     // free data if present
    00089     //
    00090     small = CmpIsHKeyValueSmall(realsize, value->u.KeyValue.DataLength);
    00091     if ((! small) && (realsize > 0))
    00092     {
    00093         HvFreeCell(Hive, value->u.KeyValue.Data);
    00094     }
    00095
    00096     //
    00097     // free the cell itself
    00098     //
    00099     HvFreeCell(Hive, Cell);
    00100
    00101     return;
    00102 }

PCM_NAME_CONTROL_BLOCK CmpGetNameControlBlock | ( | PUNICODE_STRING | NodeName | ) |

Definition at line 368 of file cmsubs.c.

References CmpCompareCompressedName(), CmpNameCacheTable, _CM_NAME_CONTROL_BLOCK::Compressed, _CM_NAME_HASH::ConvKey, _CM_NAME_CONTROL_BLOCK::ConvKey, ExAllocatePoolWithTag, FALSE, GET_HASH_INDEX, Index, _CM_NAME_CONTROL_BLOCK::Name, Name, _CM_NAME_CONTROL_BLOCK::NameHash, _CM_NAME_CONTROL_BLOCK::NameLength, _CM_NAME_HASH::NextHash, NULL, PagedPool, PROTECTED_POOL, _CM_NAME_CONTROL_BLOCK::RefCount, RtlUpcaseUnicodeChar(), Size, TRUE, and USHORT.

Referenced by CmpCreateKeyControlBlock().

    00371 {
    00372     PCM_NAME_CONTROL_BLOCK   Ncb;
    00373     ULONG  Cnt;
    00374     WCHAR *Cp;
    00375     WCHAR *Cp2;
    00376     ULONG Index;
    00377     ULONG i;
    00378     ULONG      Size;
    00379     PCM_NAME_HASH CurrentName;
    00380     ULONG rc;
    00381     BOOLEAN NameFound = FALSE;
    00382     USHORT NameSize;
    00383     BOOLEAN NameCompressed;
    00384     ULONG NameConvKey=0;
    00385     LONG Result;
    00386
    00387     //
    00388     // Calculate the ConvKey for this NadeName;
    00389     //
    00390
    00391     Cp = NodeName->Buffer;
    00392     for (Cnt=0; Cnt<NodeName->Length; Cnt += sizeof(WCHAR)) {
    00393         if (*Cp != OBJ_NAME_PATH_SEPARATOR) {
    00394             NameConvKey = 37 * NameConvKey + (ULONG) RtlUpcaseUnicodeChar(*Cp);
    00395         }
    00396         ++Cp;
    00397     }
    00398
    00399     //
    00400     // Find the Name Size;
    00401     //
    00402     NameCompressed = TRUE;
    00403     NameSize = NodeName->Length / sizeof(WCHAR);
    00404     for (i=0;i<NodeName->Length/sizeof(WCHAR);i++) {
    00405         if ((USHORT)NodeName->Buffer[i] > (UCHAR)-1) {
    00406             NameSize = NodeName->Length;
    00407             NameCompressed = FALSE;
    00408         }
    00409     }
    00410
    00411     Index = GET_HASH_INDEX(NameConvKey);
    00412     CurrentName = CmpNameCacheTable[Index];
    00413
    00414     while (CurrentName) {
    00415         Ncb =  CONTAINING_RECORD(CurrentName, CM_NAME_CONTROL_BLOCK, NameHash);
    00416
    00417         if ((NameConvKey == CurrentName->ConvKey) &&
    00418             (NameSize == Ncb->NameLength)) {
    00419             //
    00420             // Hash value matches, compare the names.
    00421             //
    00422             NameFound = TRUE;
    00423             if (Ncb->Compressed) {
    00424                 if (CmpCompareCompressedName(NodeName, Ncb->Name, NameSize)) {
    00425                     NameFound = FALSE;
    00426                 }
    00427             } else {
    00428                 Cp = (WCHAR *) NodeName->Buffer;
    00429                 Cp2 = (WCHAR *) Ncb->Name;
    00430                 for (i=0 ;i<Ncb->NameLength; i+= sizeof(WCHAR)) {
    00431                     if (RtlUpcaseUnicodeChar(*Cp) != RtlUpcaseUnicodeChar(*Cp2)) {
    00432                         NameFound = FALSE;
    00433                         break;
    00434                     }
    00435                     ++Cp;
    00436                     ++Cp2;
    00437                 }
    00438             }
    00439             if (NameFound) {
    00440                 //
    00441                 // Found it, increase the refcount.
    00442                 //
    00443                 if ((USHORT) (Ncb->RefCount + 1) == 0) {
    00444                     //
    00445                     // We have maxed out the ref count.
    00446                     // fail the call.
    00447                     //
    00448                     Ncb = NULL;
    00449                 } else {
    00450                     ++Ncb->RefCount;
    00451                 }
    00452                 break;
    00453             }
    00454         }
    00455         CurrentName = CurrentName->NextHash;
    00456     }
    00457
    00458     if (NameFound == FALSE) {
    00459         //
    00460         // Now need to create one Name block for this string.
    00461         //
    00462         Size = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + NameSize;
    00463
    00464         Ncb = ExAllocatePoolWithTag(PagedPool,
    00465                                     Size,
    00466                                     CM_NAME_TAG | PROTECTED_POOL);
    00467
    00468         if (Ncb == NULL) {
    00469             return(NULL);
    00470         }
    00471         RtlZeroMemory(Ncb, Size);
    00472
    00473         //
    00474         // Update all the info for this newly created Name block.
    00475         //
    00476         if (NameCompressed) {
    00477             Ncb->Compressed = TRUE;
    00478             for (i=0;i<NameSize;i++) {
    00479                 ((PUCHAR)Ncb->Name)[i] = (UCHAR)(NodeName->Buffer[i]);
    00480             }
    00481         } else {
    00482             Ncb->Compressed = FALSE;
    00483             RtlCopyMemory((PVOID)(Ncb->Name), (PVOID)(NodeName->Buffer), NameSize);
    00484         }
    00485
    00486         Ncb->ConvKey = NameConvKey;
    00487         Ncb->RefCount = 1;
    00488         Ncb->NameLength = NameSize;
    00489
    00490         CurrentName = &(Ncb->NameHash);
    00491         //
    00492         // Insert into Name Hash table.
    00493         //
    00494         CurrentName->NextHash = CmpNameCacheTable[Index];
    00495         CmpNameCacheTable[Index] = CurrentName;
    00496     }
    00497
    00498     return(Ncb);
    00499 }

BOOLEAN CmpGetNextName | ( | IN OUT PUNICODE_STRING | RemainingName,
|  | OUT PUNICODE_STRING | NextName,
|  | OUT PBOOLEAN | Last
| ) |

Definition at line 860 of file cmparse.c.

References FALSE, MAX_KEY_NAME_LENGTH, NULL, TRUE, and USHORT.

Referenced by CmpParseKey(), and CmpWalkPath().

    00867                    :
    00868
    00869     This routine parses off the next component of a registry path, returning
    00870     all of the interesting state about it, including whether it's legal.
    00871
    00872 Arguments:
    00873
    00874     Current - supplies pointer to variable which points to path to parse.
    00875               on input - parsing starts from here
    00876               on output - updated to reflect starting position for next call.
    00877
    00878     NextName - supplies pointer to a unicode_string, which will be set up
    00879                to point into the parse string.
    00880
    00881     Last - supplies a pointer to a boolean - set to TRUE if this is the
    00882            last component of the name being parse, FALSE otherwise.
    00883
    00884 Return Value:
    00885
    00886     TRUE if all is well.
    00887
    00888     FALSE if illegal name (too long component, bad character, etc.)
    00889         (if false, all out parameter values are bogus.)
    00890
    00891 --*/
    00892 {
    00893     BOOLEAN rc = TRUE;
    00894
    00895     //
    00896     // Deal with NULL paths, and pointers to NULL paths
    00897     //
    00898     if ((RemainingName->Buffer == NULL) || (RemainingName->Length == 0)) {
    00899         *Last = TRUE;
    00900         NextName->Buffer = NULL;
    00901         NextName->Length = 0;
    00902         return TRUE;
    00903     }
    00904
    00905     if (*(RemainingName->Buffer) == UNICODE_NULL) {
    00906         *Last = TRUE;
    00907         NextName->Buffer = NULL;
    00908         NextName->Length = 0;
    00909         return TRUE;
    00910     }
    00911
    00912     //
    00913     // Skip over leading path separators
    00914     //
    00915     if (*(RemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR) {
    00916         RemainingName->Buffer++;
    00917         RemainingName->Length -= sizeof(WCHAR);
    00918         RemainingName->MaximumLength -= sizeof(WCHAR);
    00919     }
    00920
    00921     //
    00922     // Remember where the component starts, and scan to the end
    00923     //
    00924     NextName->Buffer = RemainingName->Buffer;
    00925     while (TRUE) {
    00926         if (RemainingName->Length == 0) {
    00927             break;
    00928         }
    00929         if (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR) {
    00930             break;
    00931         }
    00932
    00933         //
    00934         // NOT at end
    00935         // NOT another path sep
    00936         //
    00937
    00938         RemainingName->Buffer++;
    00939         RemainingName->Length -= sizeof(WCHAR);
    00940         RemainingName->MaximumLength -= sizeof(WCHAR);
    00941     }
    00942
    00943     //
    00944     // Compute component length, return error if it's illegal
    00945     //
    00946     NextName->Length = (USHORT)
    00947         ((PUCHAR)RemainingName->Buffer - (PUCHAR)(NextName->Buffer));
    00948     if (NextName->Length > MAX_KEY_NAME_LENGTH)
    00949     {
    00950         rc = FALSE;
    00951     }
    00952     NextName->MaximumLength = NextName->Length;
    00953
    00954     //
    00955     // Set last, return success
    00956     //
    00957     *Last = (RemainingName->Length == 0);
    00958     return rc;
    00959 }

PCM_KEY_VALUE CmpGetValueKeyFromCache | ( | IN PHHIVE | Hive,
|  | IN PCELL_DATA | List,
|  | IN ULONG | Index,
|  | OUT PPCM_CACHED_VALUE * | ContainingList,
|  | IN BOOLEAN | IndexCached,
|  | OUT BOOLEAN * | ValueCached
| ) |

Definition at line 200 of file cmtree.c.

References CM_CACHE_DATA_NOT_CACHED, CMP_GET_CACHED_ADDRESS, CMP_GET_CACHED_KEYVALUE, CMP_IS_CELL_CACHED, CMP_MARK_CELL_CACHED, CmpMakeSpecialPoolReadOnly, CmpMakeSpecialPoolReadWrite, _CM_CACHED_VALUE::DataCacheType, ExAllocatePoolWithTag, FALSE, Hive, HvGetCell, HvGetCellSize(), Index, _CELL_DATA::_u::KeyList, _CM_CACHED_VALUE::KeyValue, List, PagedPool, TRUE, _CELL_DATA::u, USHORT, and _CM_CACHED_VALUE::ValueKeySize.

Referenced by CmEnumerateValueKey(), and CmpFindValueByNameFromCache().

    00210                    :
    00211
    00212     Get the Valve Node.  Check if it is already cached, if not but the index is cached,
    00213     cache and return the value node.
    00214
    00215 Arguments:
    00216
    00217     Hive - pointer to hive control structure for hive of interest.
    00218
    00219     List - pointer to the Value Index Array (of ULOONG_PTR if cached and ULONG if non-cached)
    00220
    00221     Index - Index in the Value index array
    00222
    00223     ContainlingList - The address of the entry that will receive the found cached value.
    00224
    00225     IndexCached - Indicate if the index list is cached.  If not, everything is from the
    00226                   original registry data.
    00227
    00228     ValueCached - Indicating whether Value is cached or not.
    00229
    00230 Return Value:
    00231
    00232     Pointer to the Valve Node.
    00233 --*/
    00234 {
    00235     PCM_KEY_VALUE pchild;
    00236     PULONG_PTR    CachedList;
    00237     ULONG AllocSize;
    00238     ULONG CopySize;
    00239     PCM_CACHED_VALUE CachedValue;
    00240
    00241     if (IndexCached) {
    00242         //
    00243         // The index array is cached, so List is pointing to an array of ULONG_PTR.
    00244         // Use CachedList.
    00245         //
    00246         CachedList = (PULONG_PTR) List;
    00247         *ValueCached = TRUE;
    00248         if (CMP_IS_CELL_CACHED(CachedList[Index])) {
    00249             pchild = CMP_GET_CACHED_KEYVALUE(CachedList[Index]);
    00250             *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]);
    00251         } else {
    00252             pchild = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]);
    00253             //
    00254             // Allocate a PagedPool to cache the value node.
    00255             //
    00256             CopySize = (ULONG) HvGetCellSize(Hive, pchild);
    00257             AllocSize = CopySize + FIELD_OFFSET(CM_CACHED_VALUE, KeyValue);
    00258
    00259             // Dragos: Changed to catch the memory violator
    00260             // it didn't work
    00261             //CachedValue = (PCM_CACHED_VALUE) ExAllocatePoolWithTagPriority(PagedPool, AllocSize, CM_CACHE_VALUE_TAG,NormalPoolPrioritySpecialPoolUnderrun);
    00262             CachedValue = (PCM_CACHED_VALUE) ExAllocatePoolWithTag(PagedPool, AllocSize, CM_CACHE_VALUE_TAG);
    00263
    00264             if (CachedValue) {
    00265                 //
    00266                 // Set the information for later use if we need to cache data as well.
    00267                 //
    00268                 CachedValue->DataCacheType = CM_CACHE_DATA_NOT_CACHED;
    00269                 CachedValue->ValueKeySize = (USHORT) CopySize;
    00270
    00271                 RtlCopyMemory((PVOID)&(CachedValue->KeyValue), pchild, CopySize);
    00272
    00273
    00274                 // Trying to catch the BAD guy who writes over our pool.
    00275                 CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList) );
    00276
    00277                 CachedList[Index] = CMP_MARK_CELL_CACHED(CachedValue);
    00278
    00279                 // Trying to catch the BAD guy who writes over our pool.
    00280                 CmpMakeSpecialPoolReadOnly( CMP_GET_CACHED_ADDRESS(CachedList) );
    00281
    00282
    00283                 // Trying to catch the BAD guy who writes over our pool.
    00284                 CmpMakeSpecialPoolReadOnly(CachedValue);
    00285
    00286                 *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]);
    00287                 //
    00288                 // Now we have the stuff cached, use the cache data.
    00289                 //
    00290                 pchild = CMP_GET_CACHED_KEYVALUE(CachedValue);
    00291             } else {
    00292                 //
    00293                 // If the allocation fails, just do not cache it. continue.
    00294                 //
    00295                 *ValueCached = FALSE;
    00296             }
    00297         }
    00298     } else {
    00299         //
    00300         // The Valve Index Array is from the registry hive, just get the cell and move on.
    00301         //
    00302         pchild = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]);
    00303         *ValueCached = FALSE;
    00304     }
    00305     return (pchild);
    00306 }

PCELL_DATA CmpGetValueListFromCache | ( | IN PHHIVE | Hive,
|  | IN PCACHED_CHILD_LIST | ChildList,
|  | IN OUT BOOLEAN * | IndexCached
| ) |

PSECURITY_DESCRIPTOR CmpHiveRootSecurityDescriptor | ( | VOID |  | ) |

Definition at line 1227 of file cmse.c.

References ASSERT, CML_MAJOR, CMLOG, CMS_SEC, ExAllocatePool, ExFreePool(), FALSE, KeBugCheckEx(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, RtlAddAccessAllowedAce(), RtlCreateAcl(), RtlCreateSecurityDescriptor(), RtlGetAce(), RtlInitializeSid(), RtlLengthRequiredSid(), RtlSetDaclSecurityDescriptor(), RtlSubAuthoritySid(), RtlValidSid(), SeLengthSid, Status, TRUE, and WorldSid.

Referenced by CmInitSystem1(), CmpCreateRegistryRoot(), CmpInitializeHiveList(), CmpInitializeSystemHive(), and CmpSetVersionData().

    01232                    :
    01233
    01234     This routine allocates and initializes the default security descriptor
    01235     for a system-created registry key.
    01236
    01237     The caller is responsible for freeing the allocated security descriptor
    01238     when he is done with it.
    01239
    01240 Arguments:
    01241
    01242     None
    01243
    01244 Return Value:
    01245
    01246     Pointer to an initialized security descriptor if successful.
    01247
    01248     Bugcheck otherwise.
    01249
    01250 --*/
    01251
    01252 {
    01253     NTSTATUS Status;
    01254     PSECURITY_DESCRIPTOR SecurityDescriptor=NULL;
    01255     PACL Acl=NULL;
    01256     PACL AclCopy;
    01257     PSID WorldSid=NULL;
    01258     PSID RestrictedSid=NULL;
    01259     PSID SystemSid=NULL;
    01260     PSID AdminSid=NULL;
    01261     SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
    01262     SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
    01263     ULONG AceLength;
    01264     ULONG AclLength;
    01265     PACE_HEADER AceHeader;
    01266
    01267     PAGED_CODE();
    01268
    01269     //
    01270     // Allocate and initialize the SIDs we will need.
    01271     //
    01272     WorldSid  = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1));
    01273     RestrictedSid  = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1));
    01274     SystemSid = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1));
    01275     AdminSid  = ExAllocatePool(PagedPool, RtlLengthRequiredSid(2));
    01276     if ((WorldSid  == NULL) ||
    01277         (RestrictedSid == NULL) ||
    01278         (SystemSid == NULL) ||
    01279         (AdminSid  == NULL)) {
    01280
    01281         KeBugCheckEx(REGISTRY_ERROR, 10, 0, 0, 0);
    01282     }
    01283
    01284     if ((!NT_SUCCESS(RtlInitializeSid(WorldSid, &WorldAuthority, 1))) ||
    01285         (!NT_SUCCESS(RtlInitializeSid(RestrictedSid, &NtAuthority, 1))) ||
    01286         (!NT_SUCCESS(RtlInitializeSid(SystemSid, &NtAuthority, 1))) ||
    01287         (!NT_SUCCESS(RtlInitializeSid(AdminSid, &NtAuthority, 2)))) {
    01288         KeBugCheckEx(REGISTRY_ERROR, 10, 1, 0, 0);
    01289     }
    01290
    01291     *(RtlSubAuthoritySid(WorldSid, 0)) = SECURITY_WORLD_RID;
    01292
    01293     *(RtlSubAuthoritySid(RestrictedSid, 0)) = SECURITY_RESTRICTED_CODE_RID;
    01294
    01295     *(RtlSubAuthoritySid(SystemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID;
    01296
    01297     *(RtlSubAuthoritySid(AdminSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
    01298     *(RtlSubAuthoritySid(AdminSid, 1)) = DOMAIN_ALIAS_RID_ADMINS;
    01299
    01300     ASSERT(RtlValidSid(WorldSid));
    01301     ASSERT(RtlValidSid(RestrictedSid));
    01302     ASSERT(RtlValidSid(SystemSid));
    01303     ASSERT(RtlValidSid(AdminSid));
    01304
    01305     //
    01306     // Compute the size of the ACE list
    01307     //
    01308
    01309     AceLength = (SeLengthSid(WorldSid)  -
    01310                  sizeof(ULONG)          +
    01311                  sizeof(ACCESS_ALLOWED_ACE))
    01312               + (SeLengthSid(RestrictedSid)  -
    01313                  sizeof(ULONG)          +
    01314                  sizeof(ACCESS_ALLOWED_ACE))
    01315               + (SeLengthSid(SystemSid) -
    01316                  sizeof(ULONG)          +
    01317                  sizeof(ACCESS_ALLOWED_ACE))
    01318               + (SeLengthSid(AdminSid)  -
    01319                  sizeof(ULONG)          +
    01320                  sizeof(ACCESS_ALLOWED_ACE));
    01321
    01322     //
    01323     // Allocate and initialize the ACL
    01324     //
    01325
    01326     AclLength = AceLength + sizeof(ACL);
    01327     Acl = ExAllocatePool(PagedPool, AclLength);
    01328     if (Acl == NULL) {
    01329         CMLOG(CML_MAJOR, CMS_SEC) {
    01330             KdPrint(("CmpHiveRootSecurityDescriptor: couldn't allocate ACL\n"));
    01331         }
    01332
    01333         KeBugCheckEx(REGISTRY_ERROR, 10, 2, 0, 0);
    01334     }
    01335
    01336     Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
    01337     if (!NT_SUCCESS(Status)) {
    01338         CMLOG(CML_MAJOR, CMS_SEC) {
    01339             KdPrint(("CmpHiveRootSecurityDescriptor: couldn't initialize ACL\n"));
    01340         }
    01341         KeBugCheckEx(REGISTRY_ERROR, 10, 3, 0, 0);
    01342     }
    01343
    01344     //
    01345     // Now add the ACEs to the ACL
    01346     //
    01347     Status = RtlAddAccessAllowedAce(Acl,
    01348                                     ACL_REVISION,
    01349                                     KEY_ALL_ACCESS,
    01350                                     SystemSid);
    01351     if (NT_SUCCESS(Status)) {
    01352         Status = RtlAddAccessAllowedAce(Acl,
    01353                                         ACL_REVISION,
    01354                                         KEY_ALL_ACCESS,
    01355                                         AdminSid);
    01356     }
    01357     if (NT_SUCCESS(Status)) {
    01358         Status = RtlAddAccessAllowedAce(Acl,
    01359                                         ACL_REVISION,
    01360                                         KEY_READ,
    01361                                         WorldSid);
    01362     }
    01363     if (NT_SUCCESS(Status)) {
    01364         Status = RtlAddAccessAllowedAce(Acl,
    01365                                         ACL_REVISION,
    01366                                         KEY_READ,
    01367                                         RestrictedSid);
    01368     }
    01369     if (!NT_SUCCESS(Status)) {
    01370         CMLOG(CML_MAJOR, CMS_SEC) {
    01371             KdPrint(("CmpHiveRootSecurityDescriptor: RtlAddAce failed status %08lx\n", Status));
    01372         }
    01373
    01374         KeBugCheckEx(REGISTRY_ERROR, 10, 4, 0, 0);
    01375     }
    01376
    01377     //
    01378     // Make the ACEs inheritable
    01379     //
    01380     Status = RtlGetAce(Acl,0,&AceHeader);
    01381     ASSERT(NT_SUCCESS(Status));
    01382     AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    01383
    01384     Status = RtlGetAce(Acl,1,&AceHeader);
    01385     ASSERT(NT_SUCCESS(Status));
    01386     AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    01387
    01388     Status = RtlGetAce(Acl,2,&AceHeader);
    01389     ASSERT(NT_SUCCESS(Status));
    01390     AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    01391
    01392     Status = RtlGetAce(Acl,3,&AceHeader);
    01393     ASSERT(NT_SUCCESS(Status));
    01394     AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    01395     //
    01396     // We are finally ready to allocate and initialize the security descriptor
    01397     // Allocate enough space to hold both the security descriptor and the
    01398     // ACL.  This allows us to free the whole thing at once when we are
    01399     // done with it.
    01400     //
    01401
    01402     SecurityDescriptor = ExAllocatePool(
    01403                             PagedPool,
    01404                             sizeof(SECURITY_DESCRIPTOR) + AclLength
    01405                             );
    01406
    01407     if (SecurityDescriptor == NULL) {
    01408         CMLOG(CML_MAJOR, CMS_SEC) {
    01409             KdPrint(("CmpHiveRootSecurityDescriptor: Couldn't allocate Sec. Desc.\n"));
    01410         }
    01411         KeBugCheckEx(REGISTRY_ERROR, 10, 5, 0, 0);
    01412     }
    01413
    01414     AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor+1);
    01415     RtlMoveMemory(AclCopy, Acl, AclLength);
    01416
    01417     Status = RtlCreateSecurityDescriptor( SecurityDescriptor,
    01418                                           SECURITY_DESCRIPTOR_REVISION );
    01419     if (!NT_SUCCESS(Status)) {
    01420         CMLOG(CML_MAJOR, CMS_SEC) {
    01421             KdPrint(("CmpHiveRootSecurityDescriptor: CreateSecDesc failed %08lx\n",Status));
    01422         }
    01423         ExFreePool(SecurityDescriptor);
    01424         SecurityDescriptor=NULL;
    01425         KeBugCheckEx(REGISTRY_ERROR, 10, 6, 0, 0);
    01426     }
    01427
    01428     Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor,
    01429                                            TRUE,
    01430                                            AclCopy,
    01431                                            FALSE );
    01432     if (!NT_SUCCESS(Status)) {
    01433         CMLOG(CML_MAJOR, CMS_SEC) {
    01434             KdPrint(("CmpHiveRootSecurityDescriptor: SetDacl failed %08lx\n",Status));
    01435         }
    01436         ExFreePool(SecurityDescriptor);
    01437         SecurityDescriptor=NULL;
    01438         KeBugCheckEx(REGISTRY_ERROR, 10, 7, 0, 0);
    01439     }
    01440
    01441     //
    01442     // free any allocations we made
    01443     //
    01444     if (WorldSid!=NULL) {
    01445         ExFreePool(WorldSid);
    01446     }
    01447     if (RestrictedSid!=NULL) {
    01448         ExFreePool(RestrictedSid);
    01449     }
    01450     if (SystemSid!=NULL) {
    01451         ExFreePool(SystemSid);
    01452     }
    01453     if (AdminSid!=NULL) {
    01454         ExFreePool(AdminSid);
    01455     }
    01456     if (Acl!=NULL) {
    01457         ExFreePool(Acl);
    01458     }
    01459
    01460     return(SecurityDescriptor);
    01461 }

NTSTATUS CmpInitHiveFromFile | ( | IN PUNICODE_STRING | FileName,
|  | IN ULONG | HiveFlags,
|  | OUT PCMHIVE * | CmHive,
|  | IN OUT PBOOLEAN | Allocate,
|  | IN OUT PBOOLEAN | RegistryLocked
| ) |

Definition at line 2422 of file cmsysini.c.

References CmpInitializeHive(), CmpLockRegistryExclusive(), CmpOpenHiveFiles(), FALSE, FileName, HFILE_TYPE_LOG, HFILE_TYPE_PRIMARY, HINIT_CREATE, HINIT_FILE, L, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, and TRUE.

Referenced by CmpInitializeHiveList(), and CmpWorker().

    02432                    :
    02433
    02434     This routine opens a file and log, allocates a CMHIVE, and initializes
    02435     it.
    02436
    02437 Arguments:
    02438
    02439     FileName - Supplies name of file to be loaded.
    02440
    02441     HiveFlags - Supplies hive flags to be passed to CmpInitializeHive
    02442
    02443     CmHive   - Returns pointer to initialized hive (if successful)
    02444
    02445     Allocate - IN: if TRUE ok to allocate, if FALSE hive must exist
    02446                     (bug .log may get created)
    02447                OUT: TRUE if actually created hive, FALSE if existed before
    02448
    02449 Return Value:
    02450
    02451     NTSTATUS
    02452
    02453 --*/
    02454
    02455 {
    02456     PCMHIVE NewHive;
    02457     ULONG Disposition;
    02458     ULONG SecondaryDisposition;
    02459     HANDLE PrimaryHandle;
    02460     HANDLE LogHandle;
    02461     NTSTATUS Status;
    02462     ULONG FileType;
    02463     ULONG Operation;
    02464
    02465     BOOLEAN Success;
    02466
    02467     PAGED_CODE();
    02468     *CmHive = NULL;
    02469
    02470     Status = CmpOpenHiveFiles(FileName,
    02471                               L".LOG",
    02472                               &PrimaryHandle,
    02473                               &LogHandle,
    02474                               &Disposition,
    02475                               &SecondaryDisposition,
    02476                               *Allocate,
    02477                               FALSE,
    02478                               NULL);
    02479
    02480     if (!NT_SUCCESS(Status)) {
    02481         return(Status);
    02482     }
    02483
    02484     if (LogHandle == NULL) {
    02485         FileType = HFILE_TYPE_PRIMARY;
    02486     } else {
    02487         FileType = HFILE_TYPE_LOG;
    02488     }
    02489
    02490     if (Disposition == FILE_CREATED) {
    02491         Operation = HINIT_CREATE;
    02492         *Allocate = TRUE;
    02493     } else {
    02494         Operation = HINIT_FILE;
    02495         *Allocate = FALSE;
    02496     }
    02497
    02498     if( !(*RegistryLocked) ) {
    02499         //
    02500         // Registry should be locked exclusive
    02501         // if not, lock it now and signal this to the caller
    02502         //
    02503         CmpLockRegistryExclusive();
    02504         *RegistryLocked = TRUE;
    02505     }
    02506
    02507     Status = CmpInitializeHive(&NewHive,
    02508                                 Operation,
    02509                                 HiveFlags,
    02510                                 FileType,
    02511                                 NULL,
    02512                                 PrimaryHandle,
    02513                                 NULL,
    02514                                 LogHandle,
    02515                                 NULL,
    02516                                 FileName
    02517                                 );
    02518     if (!NT_SUCCESS(Status)) {
    02519         ZwClose(PrimaryHandle);
    02520         if (LogHandle != NULL) {
    02521             ZwClose(LogHandle);
    02522         }
    02523         return(Status);
    02524     } else {
    02525         *CmHive = NewHive;
    02526         return(STATUS_SUCCESS);
    02527     }
    02528 }

VOID CmpInitializeCache | ( | VOID |  | ) |

NTSTATUS CmpInitializeHardwareConfiguration | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock | ) |

Definition at line 87 of file cmconfig.c.

References ASSERT, CmpConfigurationAreaSize, CmpConfigurationData, CmpSetupConfigurationTree(), CmRegistryMachineHardwareDescriptionName, CmRegistryMachineHardwareDeviceMapName, _CONFIGURATION_COMPONENT_DATA::ComponentEntry, ExAllocatePool, ExFreePool(), _CONFIGURATION_COMPONENT::Identifier, KeFindConfigurationEntry(), KeI386MachineType, MaximumType, NT_SUCCESS, NtClose(), NtCreateKey(), NTSTATUS(), NULL, ObjectAttributes, PagedPool, Status, SystemClass, and TITLE_INDEX_VALUE.

Referenced by CmInitSystem1().

    00092                    :
    00093
    00094     This routine creates \\Registry\Machine\Hardware node in
    00095     the registry and calls SetupTree routine to put the hardware
    00096     information to the registry.
    00097
    00098 Arguments:
    00099
    00100     LoaderBlock - supplies a pointer to the LoaderBlock passed in from the
    00101                   OS Loader.
    00102
    00103 Returns:
    00104
    00105     NTSTATUS code for sucess or reason of failure.
    00106
    00107 --*/
    00108 {
    00109     NTSTATUS Status;
    00110     OBJECT_ATTRIBUTES ObjectAttributes;
    00111     HANDLE BaseHandle;
    00112     PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
    00113     ULONG Disposition;
    00114
    00115     ConfigurationRoot = (PCONFIGURATION_COMPONENT_DATA)LoaderBlock->ConfigurationRoot;
    00116     if (ConfigurationRoot) {
    00117
    00118 #ifdef _X86_
    00119
    00120         //
    00121         //  The following strings found in the registry identify obscure,
    00122         //  yet market dominant, non PC/AT compatible i386 machine in Japan.
    00123         //
    00124
    00125 #define MACHINE_TYPE_FUJITSU_FMR_NAME_A    "FUJITSU FMR-"
    00126 #define MACHINE_TYPE_NEC_PC98_NAME_A       "NEC PC-98"
    00127
    00128         {
    00129             PCONFIGURATION_COMPONENT_DATA SystemNode;
    00130             ULONG JapanMachineId;
    00131
    00132             //
    00133             // For Japan, we have to special case some non PC/AT machines, so
    00134             // determine at this time what kind of platform we are on:
    00135             //
    00136             // NEC PC9800 Compatibles/Fujitsu FM-R Compatibles/IBM PC/AT Compatibles
    00137             //
    00138             // Default is PC/AT compatible.
    00139             //
    00140
    00141             JapanMachineId = MACHINE_TYPE_PC_AT_COMPATIBLE;
    00142
    00143             //
    00144             // Find the hardware description node
    00145             //
    00146
    00147             SystemNode = KeFindConfigurationEntry(ConfigurationRoot,
    00148                                                   SystemClass,
    00149                                                   MaximumType,
    00150                                                   NULL);
    00151
    00152             //
    00153             // Did we find something?
    00154             //
    00155
    00156             if (SystemNode) {
    00157
    00158                 //
    00159                 // Check platform from identifier string
    00160                 //
    00161
    00162                 if (RtlCompareMemory(SystemNode->ComponentEntry.Identifier,
    00163                                      MACHINE_TYPE_NEC_PC98_NAME_A,
    00164                                      sizeof(MACHINE_TYPE_NEC_PC98_NAME_A) - 1) ==
    00165                     sizeof(MACHINE_TYPE_NEC_PC98_NAME_A) - 1) {
    00166
    00167                     //
    00168                     // we are running on NEC PC-9800 comaptibles.
    00169                     //
    00170
    00171                     JapanMachineId = MACHINE_TYPE_PC_9800_COMPATIBLE;
    00172                     SetNEC_98;
    00173
    00174                 } else if (RtlCompareMemory(SystemNode->ComponentEntry.Identifier,
    00175                                             MACHINE_TYPE_FUJITSU_FMR_NAME_A,
    00176                                             sizeof(MACHINE_TYPE_FUJITSU_FMR_NAME_A) - 1) ==
    00177                            sizeof(MACHINE_TYPE_FUJITSU_FMR_NAME_A) - 1) {
    00178
    00179                     //
    00180                     // we are running on Fujitsu FMR comaptibles.
    00181                     //
    00182
    00183                     JapanMachineId = MACHINE_TYPE_FMR_COMPATIBLE;
    00184                 }
    00185             }
    00186
    00187             //
    00188             //  Now 'or' this value into the kernel global.
    00189             //
    00190
    00191             KeI386MachineType |= JapanMachineId;
    00192         }
    00193 #endif //_X86_
    00194
    00195         //
    00196         // Create \\Registry\Machine\Hardware\DeviceMap
    00197         //
    00198
    00199         InitializeObjectAttributes(
    00200             &ObjectAttributes,
    00201             &CmRegistryMachineHardwareDeviceMapName,
    00202             0,
    00203             (HANDLE)NULL,
    00204             NULL
    00205             );
    00206         ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
    00207
    00208         Status = NtCreateKey(                   // Paht may already exist
    00209                     &BaseHandle,
    00210                     KEY_READ | KEY_WRITE,
    00211                     &ObjectAttributes,
    00212                     TITLE_INDEX_VALUE,
    00213                     NULL,
    00214                     0,
    00215                     &Disposition
    00216                     );
    00217
    00218         if (!NT_SUCCESS(Status)) {
    00219             return(Status);
    00220         }
    00221
    00222         NtClose(BaseHandle);
    00223
    00224         ASSERT(Disposition == REG_CREATED_NEW_KEY);
    00225
    00226         //
    00227         // Create \\Registry\Machine\Hardware\Description and use the
    00228         // returned handle as the BaseHandle to build the hardware tree.
    00229         //
    00230
    00231         InitializeObjectAttributes(
    00232             &ObjectAttributes,
    00233             &CmRegistryMachineHardwareDescriptionName,
    00234             0,
    00235             (HANDLE)NULL,
    00236             NULL
    00237             );
    00238         ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
    00239
    00240         Status = NtCreateKey(                   // Path may already exist
    00241                     &BaseHandle,
    00242                     KEY_READ | KEY_WRITE,
    00243                     &ObjectAttributes,
    00244                     TITLE_INDEX_VALUE,
    00245                     NULL,
    00246                     0,
    00247                     &Disposition
    00248                     );
    00249
    00250         if (!NT_SUCCESS(Status)) {
    00251             return(Status);
    00252         }
    00253
    00254         ASSERT(Disposition == REG_CREATED_NEW_KEY);
    00255
    00256         //
    00257         // Allocate 16K bytes memory from paged pool for constructing
    00258         // configuration data for controller component.
    00259         // NOTE:  The configuration Data for controller component
    00260         //    usually takes less than 100 bytes.  But on EISA machine, the
    00261         //    EISA configuration information takes more than 10K and up to
    00262         //    64K.  I believe 16K is the reasonable number to handler 99.9%
    00263         //    of the machines.  Therefore, 16K is the initial value.
    00264         //
    00265
    00266         CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
    00267                                             PagedPool,
    00268                                             CmpConfigurationAreaSize
    00269                                             );
    00270
    00271         if (CmpConfigurationData == NULL) {
    00272             return(STATUS_INSUFFICIENT_RESOURCES);
    00273         }
    00274
    00275         //
    00276         // Call SetupConfigurationTree routine to go over each component
    00277         // of the tree and add component information to registry database.
    00278         //
    00279
    00280         Status = CmpSetupConfigurationTree(ConfigurationRoot,
    00281                                            BaseHandle,
    00282                                            -1,
    00283                                            (ULONG)-1
    00284                                            );
    00285         ExFreePool((PVOID)CmpConfigurationData);
    00286         NtClose(BaseHandle);
    00287         return(Status);
    00288     } else {
    00289         return(STATUS_SUCCESS);
    00290     }
    00291 }

NTSTATUS CmpInitializeHive | ( | PCMHIVE * | CmHive,
|  | ULONG | OperationType,
|  | ULONG | HiveFlags,
|  | ULONG | FileType,
|  | PVOID HiveData | OPTIONAL,
|  | HANDLE | Primary,
|  | HANDLE | Alternate,
|  | HANDLE | Log,
|  | HANDLE | External,
|  | PUNICODE_STRING | FileName
| ) |

Definition at line 471 of file cminit.c.

References ASSERT, ASSERT_PASSIVE_LEVEL, CmCheckRegistry(), CMHIVE, CML_MAJOR, CMLOG, CmpAllocate(), CmpFileFlush(), CmpFileRead(), CmpFileSetSize(), CmpFileWrite(), CmpFree(), CmpHiveListHead, CMS_INIT, CMS_INIT_ERROR, ExAllocatePoolWithTag, ExFreePool(), ExInitializeFastMutex, FALSE, _CMHIVE::FileHandles, FileName, HBLOCK_SIZE, HFILE_TYPE_ALTERNATE, HFILE_TYPE_EXTERNAL, HFILE_TYPE_LOG, HFILE_TYPE_MAX, HFILE_TYPE_PRIMARY, HINIT_FILE, HINIT_MEMORY, HINIT_MEMORY_INPLACE, _CMHIVE::Hive, HIVE_VOLATILE, _CMHIVE::HiveList, _CMHIVE::HiveLock, HSECTOR_SIZE, HvFreeHive(), HvInitializeHive(), NonPagedPool, _CMHIVE::NotifyList, NT_SUCCESS, NTSTATUS(), NULL, Status, and TRUE.

Referenced by CmInitSystem1(), CmpCreateTemporaryHive(), CmpInitHiveFromFile(), CmpInitializeSystemHive(), CmpLoadHiveVolatile(), CmpValidateAlternate(), CmRestoreKey(), EhOpenHive(), and MyCmpInitHiveFromFile().

    00485                    :
    00486
    00487     Initialize a hive.
    00488
    00489 Arguments:
    00490
    00491     CmHive - pointer to a variable to receive a pointer to the CmHive structure
    00492
    00493     OperationType - specifies whether to create a new hive from scratch,
    00494             from a memory image, or by reading a file from disk.
    00495             [HINIT_CREATE | HINIT_MEMORY | HINIT_FILE ]
    00496
    00497     HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless
    00498                                    of the types of cells allocated
    00499                 HIVE_NO_LAZY_FLUSH - Data in this hive is never written
    00500                                    to disk except by an explicit FlushKey
    00501
    00502     FileType - HFILE_TYPE_*, HFILE_TYPE_LOG or HFILE_TYPE_ALTERNATE set
    00503             up for logging or alternate support respectively.
    00504
    00505     HiveData - if present, supplies a pointer to an in memory image of
    00506             from which to init the hive.  Only useful when OperationType
    00507             is set to HINIT_MEMORY.
    00508
    00509     Primary - File handle for primary hive file (e.g. SYSTEM)
    00510
    00511     Alternate - File handle for alternate hive file (e.g. SYSTEM.ALT)
    00512
    00513     Log - File handle for log hive file (e.g. SOFTWARE.LOG)
    00514
    00515     External - File handle for primary hive file  (e.g.  BACKUP.REG)
    00516
    00517     FileName - some path like "...\system32\config\system", which will
    00518                 be written into the base block as an aid to debugging.
    00519                 may be NULL.
    00520
    00521 Return Value:
    00522
    00523     NTSTATUS
    00524
    00525 --*/
    00526 {
    00527     FILE_FS_SIZE_INFORMATION    FsSizeInformation;
    00528     IO_STATUS_BLOCK             IoStatusBlock;
    00529     ULONG                       Cluster;
    00530     NTSTATUS                    Status;
    00531     PCMHIVE                     cmhive2;
    00532     ULONG                       rc;
    00533
    00534     CMLOG(CML_MAJOR, CMS_INIT) {
    00535         KdPrint(("CmpInitializeHive:\t\n"));
    00536     }
    00537
    00538     //
    00539     // Reject illegal parms
    00540     //
    00541     if ( (Alternate && Log)  ||
    00542          (External && (Primary || Alternate || Log)) ||
    00543          (Alternate && !Primary) ||
    00544          (Log && !Primary) ||
    00545          ((HiveFlags & HIVE_VOLATILE) && (Alternate || Primary || External || Log)) ||
    00546          ((OperationType == HINIT_MEMORY) && (!ARGUMENT_PRESENT(HiveData))) ||
    00547          (Log && (FileType != HFILE_TYPE_LOG)) ||
    00548          (Alternate && (FileType != HFILE_TYPE_ALTERNATE))
    00549        )
    00550     {
    00551         return (STATUS_INVALID_PARAMETER);
    00552     }
    00553
    00554     //
    00555     // compute control
    00556     //
    00557     if (Primary) {
    00558
    00559         ASSERT_PASSIVE_LEVEL();
    00560         Status = ZwQueryVolumeInformationFile(
    00561                     Primary,
    00562                     &IoStatusBlock,
    00563                     &FsSizeInformation,
    00564                     sizeof(FILE_FS_SIZE_INFORMATION),
    00565                     FileFsSizeInformation
    00566                     );
    00567         if (!NT_SUCCESS(Status)) {
    00568             return (Status);
    00569         }
    00570         if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) {
    00571             return (STATUS_REGISTRY_IO_FAILED);
    00572         }
    00573         Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE;
    00574         Cluster = (Cluster < 1) ? 1 : Cluster;
    00575     } else {
    00576         Cluster = 1;
    00577     }
    00578
    00579     cmhive2 = CmpAllocate(sizeof(CMHIVE), FALSE);
    00580     if (cmhive2 == NULL) {
    00581         return (STATUS_INSUFFICIENT_RESOURCES);
    00582     }
    00583
    00584     //
    00585     // Allocate the mutex from NonPagedPool so it will not be swapped to the disk
    00586     //
    00587     cmhive2->HiveLock = (PFAST_MUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), CM_POOL_TAG );
    00588     if( cmhive2->HiveLock == NULL ) {
    00589         CmpFree(cmhive2, sizeof(CMHIVE));
    00590         return (STATUS_INSUFFICIENT_RESOURCES);
    00591     }
    00592
    00593     //
    00594     // Initialize the Cm hive control block
    00595     //
    00596     //
    00597     ASSERT((HFILE_TYPE_EXTERNAL+1) == HFILE_TYPE_MAX);
    00598     cmhive2->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
    00599     cmhive2->FileHandles[HFILE_TYPE_ALTERNATE] = Alternate;
    00600     cmhive2->FileHandles[HFILE_TYPE_LOG] = Log;
    00601     cmhive2->FileHandles[HFILE_TYPE_EXTERNAL] = External;
    00602
    00603     cmhive2->NotifyList.Flink = NULL;
    00604     cmhive2->NotifyList.Blink = NULL;
    00605
    00606     ExInitializeFastMutex(cmhive2->HiveLock);
    00607
    00608     //
    00609     // Initialize the Hv hive control block
    00610     //
    00611     Status = HvInitializeHive(
    00612                 &(cmhive2->Hive),
    00613                 OperationType,
    00614                 HiveFlags,
    00615                 FileType,
    00616                 HiveData,
    00617                 CmpAllocate,
    00618                 CmpFree,
    00619                 CmpFileSetSize,
    00620                 CmpFileWrite,
    00621                 CmpFileRead,
    00622                 CmpFileFlush,
    00623                 Cluster,
    00624                 FileName
    00625                 );
    00626     if (!NT_SUCCESS(Status)) {
    00627         CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    00628             KdPrint(("CmpInitializeHive: "));
    00629             KdPrint(("HvInitializeHive failed, Status = %08lx\n", Status));
    00630         }
    00631         ASSERT( cmhive2->HiveLock );
    00632         ExFreePool(cmhive2->HiveLock);
    00633         CmpFree(cmhive2, sizeof(CMHIVE));
    00634         return (Status);
    00635     }
    00636     if ( (OperationType == HINIT_FILE) ||
    00637          (OperationType == HINIT_MEMORY) ||
    00638          (OperationType == HINIT_MEMORY_INPLACE))
    00639     {
    00640         rc = CmCheckRegistry(cmhive2, TRUE);
    00641         if (rc != 0) {
    00642             CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    00643                 KdPrint(("CmpInitializeHive: "));
    00644                 KdPrint(("CmCheckRegistry failed, rc = %08lx\n",rc));
    00645             }
    00646             //
    00647             // in theory we should do this for MEMORY and MEMORY_INPLACE
    00648             // as well, but they're only used at init time.
    00649             //
    00650             if (OperationType == HINIT_FILE) {
    00651                 HvFreeHive((PHHIVE)cmhive2);
    00652             }
    00653             ASSERT( cmhive2->HiveLock );
    00654             ExFreePool(cmhive2->HiveLock);
    00655             CmpFree(cmhive2, sizeof(CMHIVE));
    00656             return(STATUS_REGISTRY_CORRUPT);
    00657         }
    00658     }
    00659
    00660     InsertHeadList(&CmpHiveListHead, &(cmhive2->HiveList));
    00661     *CmHive = cmhive2;
    00662     return (STATUS_SUCCESS);
    00663 }

VOID CmpInitializeKeyNameString | ( | PCM_KEY_NODE | Cell,
|  | PUNICODE_STRING | KeyName,
|  | WCHAR * | NameBuffer
| ) |

Definition at line 1515 of file cmtrecpy.c.

References Cell, CmpCompressedNameSize(), CmpCopyCompressedName(), KEY_COMP_NAME, KeyName, MAX_KEY_NAME_LENGTH, and USHORT.

Referenced by CmpCopySyncTree2(), CmpFlushNotify(), CmpFreePostBlock(), CmpNotifyChangeKey(), CmpPostNotify(), and CmpSyncSubKeysAfterDelete().

    01521                    :
    01522
    01523    Initializes a UNICODE_STRING with the name of a given key.
    01524
    01525    N.B. The initialized string's buffer is not meant
    01526          to be modified.
    01527
    01528 Arguments:
    01529
    01530    Cell       - The body of the key in question
    01531    KeyName    - The UNICODE_STRING to initialize
    01532    NameBuffer - A buffer MAX_KEY_NAME_LENGTH bytes in size
    01533                 that will possibly be used as the UNICODE_STRING's
    01534                 buffer.
    01535
    01536 Return Value:
    01537
    01538    NONE.
    01539
    01540 --*/
    01541 {
    01542    // is the name stored in compressed form?
    01543
    01544    if(Cell->Flags & KEY_COMP_NAME) {
    01545
    01546       // Name is compressed.
    01547
    01548       // Get the uncompressed length.
    01549
    01550       KeyName->Length = CmpCompressedNameSize(Cell->Name,
    01551                                               Cell->NameLength);
    01552
    01553       // Decompress the name into a buffer.
    01554
    01555       CmpCopyCompressedName(NameBuffer,
    01556                             MAX_KEY_NAME_LENGTH,
    01557                             Cell->Name,
    01558                             Cell->NameLength);
    01559
    01560       //
    01561       // Use the decompression buffer as the string buffer
    01562       //
    01563
    01564       KeyName->Buffer = NameBuffer;
    01565       KeyName->MaximumLength = MAX_KEY_NAME_LENGTH;
    01566
    01567    } else {
    01568
    01569       //
    01570       // Name is not compressed. Just use the name string
    01571       // from the key buffer as the string buffer.
    01572       //
    01573
    01574       KeyName->Length = Cell->NameLength;
    01575       KeyName->Buffer = Cell->Name;
    01576       KeyName->MaximumLength = (USHORT)Cell->MaxNameLen;
    01577
    01578    }
    01579 }

NTSTATUS CmpInitializeMachineDependentConfiguration | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock | ) |

Definition at line 37 of file config/alpha/init.c.

References CmRegistryMachineHardwareDescriptionSystemName, KeyName, L, NT_SUCCESS, NtOpenKey(), NtSetValueKey(), NTSTATUS(), NULL, ObjectAttributes, RtlAnsiStringToUnicodeString(), RtlFreeUnicodeString(), RtlInitAnsiString(), RtlInitUnicodeString(), Status, TITLE_INDEX_VALUE, TRUE, and ValueName.

Referenced by CmInitSystem1().

    00042                    :
    00043
    00044     This routine creates alpha specific entries in the registry.
    00045
    00046 Arguments:
    00047
    00048     LoaderBlock - supplies a pointer to the LoaderBlock passed in from the
    00049                   OS Loader.
    00050
    00051 Returns:
    00052
    00053     NTSTATUS code for sucess or reason of failure.
    00054
    00055 --*/
    00056
    00057 {
    00058
    00059     NTSTATUS Status;
    00060     UNICODE_STRING KeyName;
    00061     UNICODE_STRING ValueName;
    00062     UNICODE_STRING ValueData;
    00063     ANSI_STRING AnsiString;
    00064     OBJECT_ATTRIBUTES ObjectAttributes;
    00065     HANDLE ParentHandle;
    00066
    00067     InitializeObjectAttributes(&ObjectAttributes,
    00068                                                &CmRegistryMachineHardwareDescriptionSystemName,
    00069                                                OBJ_CASE_INSENSITIVE,
    00070                                                NULL,
    00071                                                NULL);
    00072
    00073     Status = NtOpenKey(&ParentHandle,
    00074                                KEY_READ,
    00075                                &ObjectAttributes);
    00076
    00077     if (NT_SUCCESS(Status)) {
    00078         RtlInitUnicodeString(&ValueName,
    00079                                      L"SystemBiosVersion");
    00080
    00081         RtlInitAnsiString(&AnsiString,
    00082                               &LoaderBlock->u.Alpha.FirmwareVersion[0]);
    00083
    00084         RtlAnsiStringToUnicodeString(&ValueData,
    00085                                                  &AnsiString,
    00086                                                  TRUE);
    00087
    00088         Status = NtSetValueKey(ParentHandle,
    00089                                        &ValueName,
    00090                                        TITLE_INDEX_VALUE,
    00091                                        REG_SZ,
    00092                                        ValueData.Buffer,
    00093                                        ValueData.Length + sizeof(UNICODE_NULL));
    00094
    00095         RtlFreeUnicodeString(&ValueData);
    00096
    00097         //
    00098         // If the firmware build number is included in the loader block,
    00099         // then store it in the registry.
    00100         //
    00101
    00102         if (LoaderBlock->u.Alpha.FirmwareBuildTimeStamp[0] != 0 ) {
    00103             RtlInitUnicodeString(&ValueName,
    00104                                  L"SystemBiosDate");
    00105
    00106             RtlInitAnsiString(&AnsiString,
    00107                               &LoaderBlock->u.Alpha.FirmwareBuildTimeStamp[0]);
    00108
    00109             RtlAnsiStringToUnicodeString(&ValueData,
    00110                                                          &AnsiString,
    00111                                                          TRUE);
    00112
    00113             Status = NtSetValueKey(ParentHandle,
    00114                                                &ValueName,
    00115                                                TITLE_INDEX_VALUE,
    00116                                                REG_SZ,
    00117                                                ValueData.Buffer,
    00118                                                ValueData.Length + sizeof(UNICODE_NULL));
    00119
    00120             RtlFreeUnicodeString(&ValueData);
    00121         }
    00122     }
    00123
    00124     return STATUS_SUCCESS;
    00125 }
    }

VOID CmpInitializeRegistryNames | ( | VOID |  | ) |

Definition at line 89 of file cmdatini.c.

References CmClassName, CmClassString, CmpRegistryMachineHardwareDescriptionString, CmpRegistryMachineHardwareDescriptionSystemString, CmpRegistryMachineHardwareDeviceMapString, CmpRegistryMachineHardwareOwnerMapString, CmpRegistryMachineHardwareResourceMapString, CmpRegistryMachineHardwareString, CmpRegistryMachineString, CmpRegistryMachineSystemCurrentControlSetControlBootLogString, CmpRegistryMachineSystemCurrentControlSetControlClassString, CmpRegistryMachineSystemCurrentControlSetControlSafeBootString, CmpRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagementString, CmpRegistryMachineSystemCurrentControlSetEnumRootString, CmpRegistryMachineSystemCurrentControlSetEnumString, CmpRegistryMachineSystemCurrentControlSetHardwareProfilesCurrentString, CmpRegistryMachineSystemCurrentControlSetServicesEventLogString, CmpRegistryMachineSystemCurrentControlSetServicesString, CmpRegistryMachineSystemCurrentControlSetString, CmpRegistryMachineSystemString, CmpRegistryRootString, CmpRegistrySystemCloneString, CmpRegistrySystemFileNameString, CmpRegistryUserString, CmpSymbolicLinkValueName, CmpSystemFileName, CmRegistryMachineHardwareDescriptionName, CmRegistryMachineHardwareDescriptionSystemName, CmRegistryMachineHardwareDeviceMapName, CmRegistryMachineHardwareName, CmRegistryMachineHardwareOwnerMapName, CmRegistryMachineHardwareResourceMapName, CmRegistryMachineName, CmRegistryMachineSystemCurrentControlSet, CmRegistryMachineSystemCurrentControlSetControlBootLog, CmRegistryMachineSystemCurrentControlSetControlClass, CmRegistryMachineSystemCurrentControlSetControlSafeBoot, CmRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagement, CmRegistryMachineSystemCurrentControlSetEnumName, CmRegistryMachineSystemCurrentControlSetEnumRootName, CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent, CmRegistryMachineSystemCurrentControlSetServices, CmRegistryMachineSystemCurrentControlSetServicesEventLog, CmRegistryMachineSystemName, CmRegistryRootName, CmRegistrySystemCloneName, CmRegistryUserName, CmSymbolicLinkValueName, CmTypeName, CmTypeString, MaximumClass, MaximumType, and RtlInitUnicodeString().

Referenced by CmInitSystem1().

    00095                    :
    00096
    00097     This routine creates all the Unicode strings for the various names used
    00098     in and by the registry
    00099
    00100 Arguments:
    00101
    00102     None.
    00103
    00104 Returns:
    00105
    00106     None.
    00107
    00108 --*/
    00109 {
    00110     ULONG i;
    00111
    00112     RtlInitUnicodeString( &CmRegistryRootName,
    00113                           CmpRegistryRootString );
    00114
    00115     RtlInitUnicodeString( &CmRegistryMachineName,
    00116                           CmpRegistryMachineString );
    00117
    00118     RtlInitUnicodeString( &CmRegistryMachineHardwareName,
    00119                           CmpRegistryMachineHardwareString );
    00120
    00121     RtlInitUnicodeString( &CmRegistryMachineHardwareDescriptionName,
    00122                           CmpRegistryMachineHardwareDescriptionString );
    00123
    00124     RtlInitUnicodeString( &CmRegistryMachineHardwareDescriptionSystemName,
    00125                           CmpRegistryMachineHardwareDescriptionSystemString );
    00126
    00127     RtlInitUnicodeString( &CmRegistryMachineHardwareDeviceMapName,
    00128                           CmpRegistryMachineHardwareDeviceMapString );
    00129
    00130     RtlInitUnicodeString( &CmRegistryMachineHardwareResourceMapName,
    00131                           CmpRegistryMachineHardwareResourceMapString );
    00132
    00133     RtlInitUnicodeString( &CmRegistryMachineHardwareOwnerMapName,
    00134                           CmpRegistryMachineHardwareOwnerMapString );
    00135
    00136     RtlInitUnicodeString( &CmRegistryMachineSystemName,
    00137                           CmpRegistryMachineSystemString );
    00138
    00139     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSet,
    00140                           CmpRegistryMachineSystemCurrentControlSetString);
    00141
    00142     RtlInitUnicodeString( &CmRegistryUserName,
    00143                           CmpRegistryUserString );
    00144
    00145     RtlInitUnicodeString( &CmRegistrySystemCloneName,
    00146                           CmpRegistrySystemCloneString );
    00147
    00148     RtlInitUnicodeString( &CmpSystemFileName,
    00149                           CmpRegistrySystemFileNameString );
    00150
    00151     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetEnumName,
    00152                           CmpRegistryMachineSystemCurrentControlSetEnumString);
    00153
    00154     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetEnumRootName,
    00155                           CmpRegistryMachineSystemCurrentControlSetEnumRootString);
    00156
    00157     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetServices,
    00158                           CmpRegistryMachineSystemCurrentControlSetServicesString);
    00159
    00160     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent,
    00161                           CmpRegistryMachineSystemCurrentControlSetHardwareProfilesCurrentString);
    00162
    00163     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlClass,
    00164                           CmpRegistryMachineSystemCurrentControlSetControlClassString);
    00165
    00166     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlSafeBoot,
    00167                           CmpRegistryMachineSystemCurrentControlSetControlSafeBootString);
    00168
    00169     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagement,
    00170                           CmpRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagementString);
    00171
    00172     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlBootLog,
    00173                           CmpRegistryMachineSystemCurrentControlSetControlBootLogString);
    00174
    00175     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetServicesEventLog,
    00176                           CmpRegistryMachineSystemCurrentControlSetServicesEventLogString);
    00177
    00178     RtlInitUnicodeString( &CmSymbolicLinkValueName,
    00179                           CmpSymbolicLinkValueName);
    00180
    00181 #ifdef _WANT_MACHINE_IDENTIFICATION
    00182     RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlBiosInfo,
    00183                           CmpRegistryMachineSystemCurrentControlSetControlBiosInfoString);
    00184 #endif
    00185
    00186     //
    00187     // Initialize the type names for the hardware tree.
    00188     //
    00189
    00190     for (i = 0; i <= MaximumType; i++) {
    00191
    00192         RtlInitUnicodeString( &(CmTypeName[i]),
    00193                               CmTypeString[i] );
    00194
    00195     }
    00196
    00197     //
    00198     // Initialize the class names for the hardware tree.
    00199     //
    00200
    00201     for (i = 0; i <= MaximumClass; i++) {
    00202
    00203         RtlInitUnicodeString( &(CmClassName[i]),
    00204                               CmClassString[i] );
    00205
    00206     }
    00207
    00208     return;
    00209 }
    }

NTSTATUS CmpInitializeRegistryNode | ( | IN PCONFIGURATION_COMPONENT_DATA | CurrentEntry,
|  | IN HANDLE | ParentHandle,
|  | OUT PHANDLE | NewHandle,
|  | IN INTERFACE_TYPE | InterfaceType,
|  | IN ULONG | BusNumber,
|  | IN PUSHORT | DeviceIndexTable
| ) |

Definition at line 458 of file cmconfig.c.

References ArcSystem, ASSERT, Buffer, BusNumber, _CONFIGURATION_COMPONENT::Class, CmClassName, CmpConfigurationAreaSize, CmpConfigurationData, CmTypeName, _CONFIGURATION_COMPONENT::ConfigurationDataLength, ExAllocatePool, ExFreePool(), FALSE, _CONFIGURATION_COMPONENT::Flags, Handle, _CONFIGURATION_COMPONENT::Identifier, _CONFIGURATION_COMPONENT::IdentifierLength, InterfaceType, KeyName, L, NT_SUCCESS, NtClose(), NtCreateKey(), NtSetValueKey(), NTSTATUS(), NULL, ObjectAttributes, PagedPool, RtlAnsiStringToUnicodeString(), RtlFreeUnicodeString(), RtlInitAnsiString(), RtlInitUnicodeString(), RtlIntegerToChar(), Status, SystemClass, TITLE_INDEX_VALUE, TRUE, _CONFIGURATION_COMPONENT::Type, and ValueName.

Referenced by CmpInitializeMachineDependentConfiguration(), and CmpSetupConfigurationTree().

    00469                    :
    00470
    00471     This routine creates a node for the current firmware component
    00472     and puts component data to the data part of the node.
    00473
    00474 Arguments:
    00475
    00476     CurrentEntry - Supplies a pointer to a configuration component.
    00477
    00478     Handle - Supplies the parent handle of CurrentEntry node.
    00479
    00480     NewHandle - Suppiles a pointer to a HANDLE to receive the handle of
    00481         the newly created node.
    00482
    00483     InterfaceType - Specify the Interface type of the bus that the
    00484         CurrentEntry component resides. (See BusNumber also)
    00485
    00486     BusNumber - Specify the Bus Number of the bus that the CurrentEntry
    00487         component resides on.  If Bus number is -1, it means InterfaceType
    00488         and BusNumber are meaningless for this component.
    00489
    00490 Returns:
    00491
    00492     None.
    00493
    00494 --*/
    00495 {
    00496
    00497     NTSTATUS Status;
    00498     OBJECT_ATTRIBUTES ObjectAttributes;
    00499     UNICODE_STRING KeyName;
    00500     UNICODE_STRING ValueName;
    00501     UNICODE_STRING ValueData;
    00502     HANDLE Handle;
    00503     HANDLE OldHandle;
    00504     ANSI_STRING AnsiString;
    00505     UCHAR Buffer[12];
    00506     WCHAR UnicodeBuffer[12];
    00507     CONFIGURATION_COMPONENT *Component;
    00508     ULONG Disposition;
    00509     ULONG ConfigurationDataLength;
    00510     PCM_FULL_RESOURCE_DESCRIPTOR NewArea;
    00511
    00512     Component = &CurrentEntry->ComponentEntry;
    00513
    00514     //
    00515     // If the component class is SystemClass, we set its Type to be
    00516     // ArcSystem.  The reason is because the detection code sets
    00517     // its type to MaximumType to indicate it is NOT ARC compatible.
    00518     // Here, we are only interested in building a System Node.  So we
    00519     // change its Type to ArcSystem to ease the setup.
    00520     //
    00521
    00522     if (Component->Class == SystemClass) {
    00523         Component->Type = ArcSystem;
    00524     }
    00525
    00526     //
    00527     // Create a new key to describe the Component.
    00528     //
    00529     // The type of the component will be used as the keyname of the
    00530     // registry node.  The class is the class of the component.
    00531     //
    00532
    00533     InitializeObjectAttributes(
    00534         &ObjectAttributes,
    00535         &(CmTypeName[Component->Type]),
    00536         0,
    00537         ParentHandle,
    00538         NULL
    00539         );
    00540     ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
    00541
    00542     Status = NtCreateKey(                   // Paht may already exist
    00543                 &Handle,
    00544                 KEY_READ | KEY_WRITE,
    00545                 &ObjectAttributes,
    00546                 TITLE_INDEX_VALUE,
    00547                 &(CmClassName[Component->Class]),
    00548                 0,
    00549                 &Disposition
    00550                 );
    00551
    00552     if (!NT_SUCCESS(Status)) {
    00553         return(Status);
    00554     }
    00555
    00556     //
    00557     // If this component is NOT a SystemClass component, we will
    00558     // create a subkey to identify the component's ordering.
    00559     //
    00560
    00561     if (Component->Class != SystemClass) {
    00562
    00563         RtlIntegerToChar(
    00564             DeviceIndexTable[Component->Type]++,
    00565             10,
    00566             12,
    00567             Buffer
    00568             );
    00569
    00570         RtlInitAnsiString(
    00571             &AnsiString,
    00572             Buffer
    00573             );
    00574
    00575         KeyName.Buffer = (PWSTR)UnicodeBuffer;
    00576         KeyName.Length = 0;
    00577         KeyName.MaximumLength = sizeof(UnicodeBuffer);
    00578
    00579         RtlAnsiStringToUnicodeString(
    00580             &KeyName,
    00581             &AnsiString,
    00582             FALSE
    00583             );
    00584
    00585         OldHandle = Handle;
    00586
    00587         InitializeObjectAttributes(
    00588             &ObjectAttributes,
    00589             &KeyName,
    00590             0,
    00591             OldHandle,
    00592             NULL
    00593             );
    00594         ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
    00595
    00596         Status = NtCreateKey(
    00597                     &Handle,
    00598                     KEY_READ | KEY_WRITE,
    00599                     &ObjectAttributes,
    00600                     TITLE_INDEX_VALUE,
    00601                     &(CmClassName[Component->Class]),
    00602                     0,
    00603                     &Disposition
    00604                     );
    00605
    00606         NtClose(OldHandle);
    00607
    00608         if (!NT_SUCCESS(Status)) {
    00609             return(Status);
    00610         }
    00611
    00612         ASSERT(Disposition == REG_CREATED_NEW_KEY);
    00613     }
    00614
    00615     //
    00616     // Create a value which describes the following component information:
    00617     //     Flags, Cersion, Key, AffinityMask.
    00618     //
    00619
    00620     RtlInitUnicodeString(
    00621         &ValueName,
    00622         L"Component Information"
    00623         );
    00624
    00625     Status = NtSetValueKey(
    00626                 Handle,
    00627                 &ValueName,
    00628                 TITLE_INDEX_VALUE,
    00629                 REG_BINARY,
    00630                 &Component->Flags,
    00631                 FIELD_OFFSET(CONFIGURATION_COMPONENT, ConfigurationDataLength) -
    00632                     FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)
    00633                 );
    00634
    00635     if (!NT_SUCCESS(Status)) {
    00636         NtClose(Handle);
    00637         return(Status);
    00638     }
    00639
    00640     //
    00641     // Create a value which describes the component identifier, if any.
    00642     //
    00643
    00644     if (Component->IdentifierLength) {
    00645
    00646         RtlInitUnicodeString(
    00647             &ValueName,
    00648             L"Identifier"
    00649             );
    00650
    00651         RtlInitAnsiString(
    00652             &AnsiString,
    00653             Component->Identifier
    00654             );
    00655
    00656         RtlAnsiStringToUnicodeString(
    00657             &ValueData,
    00658             &AnsiString,
    00659             TRUE
    00660             );
    00661
    00662         Status = NtSetValueKey(
    00663                     Handle,
    00664                     &ValueName,
    00665                     TITLE_INDEX_VALUE,
    00666                     REG_SZ,
    00667                     ValueData.Buffer,
    00668                     ValueData.Length + sizeof( UNICODE_NULL )
    00669                     );
    00670
    00671         RtlFreeUnicodeString(&ValueData);
    00672
    00673         if (!NT_SUCCESS(Status)) {
    00674             NtClose(Handle);
    00675             return(Status);
    00676         }
    00677     }
    00678
    00679     //
    00680     // Create a value entry for component configuration data.
    00681     //
    00682
    00683     RtlInitUnicodeString(
    00684         &ValueName,
    00685         L"Configuration Data"
    00686         );
    00687
    00688     //
    00689     // Create the configuration data based on CM_FULL_RESOURCE_DESCRIPTOR.
    00690     //
    00691     // Note the configuration data in firmware tree may be in the form of
    00692     // CM_PARTIAL_RESOURCE_LIST or nothing.  In both cases, we need to
    00693     // set up the registry configuration data to be in the form of
    00694     // CM_FULL_RESOURCE_DESCRIPTOR.
    00695     //
    00696
    00697     if (CurrentEntry->ConfigurationData) {
    00698
    00699         //
    00700         // This component has configuration data, we copy the data
    00701         // to our work area, add some more data items and copy the new
    00702         // configuration data to the registry.
    00703         //
    00704
    00705         ConfigurationDataLength = Component->ConfigurationDataLength +
    00706                       FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
    00707                       PartialResourceList);
    00708
    00709         //
    00710         // Make sure our reserved area is big enough to hold the data.
    00711         //
    00712
    00713         if (ConfigurationDataLength > CmpConfigurationAreaSize) {
    00714
    00715             //
    00716             // If reserved area is not big enough, we resize our reserved
    00717             // area.  If, unfortunately, the reallocation fails, we simply
    00718             // loss the configuration data of this particular component.
    00719             //
    00720
    00721             NewArea = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
    00722                                             PagedPool,
    00723                                             ConfigurationDataLength
    00724                                             );
    00725
    00726             if (NewArea) {
    00727                 CmpConfigurationAreaSize = ConfigurationDataLength;
    00728                 ExFreePool(CmpConfigurationData);
    00729                 CmpConfigurationData = NewArea;
    00730                 RtlMoveMemory(
    00731                     (PUCHAR)&CmpConfigurationData->PartialResourceList.Version,
    00732                     CurrentEntry->ConfigurationData,
    00733                     Component->ConfigurationDataLength
    00734                     );
    00735             } else {
    00736                 Component->ConfigurationDataLength = 0;
    00737                 CurrentEntry->ConfigurationData = NULL;
    00738             }
    00739         } else {
    00740             RtlMoveMemory(
    00741                 (PUCHAR)&CmpConfigurationData->PartialResourceList.Version,
    00742                 CurrentEntry->ConfigurationData,
    00743                 Component->ConfigurationDataLength
    00744                 );
    00745         }
    00746
    00747     }
    00748
    00749     if (CurrentEntry->ConfigurationData == NULL) {
    00750
    00751         //
    00752         // This component has NO configuration data (or we can't resize
    00753         // our reserved area to hold the data), we simple add whatever
    00754         // is required to set up a CM_FULL_RESOURCE_LIST.
    00755         //
    00756
    00757         CmpConfigurationData->PartialResourceList.Version = 0;
    00758         CmpConfigurationData->PartialResourceList.Revision = 0;
    00759         CmpConfigurationData->PartialResourceList.Count = 0;
    00760         ConfigurationDataLength = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
    00761                                                PartialResourceList) +
    00762                                   FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
    00763                                                PartialDescriptors);
    00764     }
    00765
    00766     //
    00767     // Set up InterfaceType and BusNumber for the component.
    00768     //
    00769
    00770     CmpConfigurationData->InterfaceType = InterfaceType;
    00771     CmpConfigurationData->BusNumber = BusNumber;
    00772
    00773     //
    00774     // Write the newly constructed configuration data to the hardware registry
    00775     //
    00776
    00777     Status = NtSetValueKey(
    00778                 Handle,
    00779                 &ValueName,
    00780                 TITLE_INDEX_VALUE,
    00781                 REG_FULL_RESOURCE_DESCRIPTOR,
    00782                 CmpConfigurationData,
    00783                 ConfigurationDataLength
    00784                 );
    00785
    00786     if (!NT_SUCCESS(Status)) {
    00787         NtClose(Handle);
    00788         return(Status);
    00789     }
    00790
    00791     *NewHandle = Handle;
    00792     return(STATUS_SUCCESS);
    00793
    00794 }
    }

VOID CmpInitializeValueNameString | ( | PCM_KEY_VALUE | Cell,
|  | PUNICODE_STRING | ValueName,
|  | WCHAR * | NameBuffer
| ) |

Definition at line 1582 of file cmtrecpy.c.

References Cell, CmpCompressedNameSize(), CmpCopyCompressedName(), MAX_KEY_VALUE_NAME_LENGTH, VALUE_COMP_NAME, and ValueName.

Referenced by CmpMergeKeyValues().

    01587                    :
    01588
    01589    Initializes a UNICODE_STRING with the name of a given value key.
    01590
    01591    N.B. The initialized string's buffer is not meant
    01592          to be modified.
    01593
    01594 Arguments:
    01595
    01596    Cell       - The value key in question
    01597    ValueName    - The UNICODE_STRING to initialize
    01598    NameBuffer - A buffer MAX_KEY_NAME_LENGTH bytes in size
    01599                 that will possibly be used as the UNICODE_STRING's
    01600                 buffer.
    01601
    01602 Return Value:
    01603
    01604    NONE.
    01605 */
    01606
    01607 {
    01608    // is the name stored in compressed form?
    01609
    01610    if(Cell->Flags & VALUE_COMP_NAME) {
    01611
    01612       // Name is compressed.
    01613
    01614       // Get the uncompressed length.
    01615
    01616       ValueName->Length = CmpCompressedNameSize(Cell->Name,
    01617                                               Cell->NameLength);
    01618
    01619       // Decompress the name into a buffer.
    01620
    01621       CmpCopyCompressedName(NameBuffer,
    01622                             MAX_KEY_VALUE_NAME_LENGTH,
    01623                             Cell->Name,
    01624                             Cell->NameLength);
    01625
    01626       //
    01627       // Use the decompression buffer as the string buffer
    01628       //
    01629
    01630       ValueName->Buffer = NameBuffer;
    01631       ValueName->MaximumLength = MAX_KEY_VALUE_NAME_LENGTH;
    01632
    01633    } else {
    01634
    01635       //
    01636       // Name is not compressed. Just use the name string
    01637       // from the ValueName buffer as the string buffer.
    01638       //
    01639
    01640       ValueName->Length = Cell->NameLength;
    01641       ValueName->Buffer = Cell->Name;
    01642       ValueName->MaximumLength = ValueName->Length;
    01643
    01644    }
    01645 }

BOOLEAN CmpIsLastKnownGoodBoot | ( | VOID |  | ) |

Definition at line 3863 of file cmsysini.c.

References ASSERT, CML_MAJOR, CMLOG, CMS_INIT, FALSE, L, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlQueryRegistryValues(), Status, and TRUE.

Referenced by CmBootLastKnownGood().

    03869                    :
    03870
    03871     Determines whether the current system boot is a LastKnownGood boot or
    03872     not.  It does this by comparing the following two values:
    03873
    03874         \registry\machine\system\select:Current
    03875         \registry\machine\system\select:LastKnownGood
    03876
    03877     If both of these values refer to the same control set, and this control
    03878     set is different from:
    03879
    03880         \registry\machine\system\select:Default
    03881
    03882     we are booting LastKnownGood.
    03883
    03884 Arguments:
    03885
    03886     None.
    03887
    03888 Return Value:
    03889
    03890     TRUE  - Booting LastKnownGood
    03891     FALSE - Not booting LastKnownGood
    03892
    03893 --*/
    03894
    03895 {
    03896     NTSTATUS Status;
    03897     ULONG Default;
    03898     ULONG Current;
    03899     ULONG LKG;
    03900     RTL_QUERY_REGISTRY_TABLE QueryTable[] = {
    03901         {NULL,      RTL_QUERY_REGISTRY_DIRECT,
    03902          L"Current", &Current,
    03903          REG_DWORD, (PVOID)&Current, 0 },
    03904         {NULL,      RTL_QUERY_REGISTRY_DIRECT,
    03905          L"LastKnownGood", &LKG,
    03906          REG_DWORD, (PVOID)&LKG, 0 },
    03907         {NULL,      RTL_QUERY_REGISTRY_DIRECT,
    03908          L"Default", &Default,
    03909          REG_DWORD, (PVOID)&Default, 0 },
    03910         {NULL,      0,
    03911          NULL, NULL,
    03912          REG_NONE, NULL, 0 }
    03913     };
    03914
    03915     PAGED_CODE();
    03916
    03917     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
    03918                                     L"\\Registry\\Machine\\System\\Select",
    03919                                     QueryTable,
    03920                                     NULL,
    03921                                     NULL);
    03922     //
    03923     // If this failed, something is severely wrong.
    03924     //
    03925
    03926     ASSERT(NT_SUCCESS(Status));
    03927     if (!NT_SUCCESS(Status)) {
    03928         CMLOG(CML_MAJOR, CMS_INIT) {
    03929             KdPrint(("CmpIsLastKnownGoodBoot: RtlQueryRegistryValues "));
    03930             KdPrint(("failed, Status %08lx\n", Status));
    03931         }
    03932         return(FALSE);
    03933     }
    03934
    03935     if ((LKG == Current) && (Current != Default)){
    03936         return(TRUE);
    03937     } else {
    03938         return(FALSE);
    03939     }
    03940 }

VOID CmpLazyFlush | ( | VOID |  | ) |

Definition at line 368 of file cmworker.c.

Referenced by CmpInitializeHiveList(), CmpLazyFlushWorker(), and HvMarkDirty().

    00374                    :
    00375
    00376     This routine resets the registry timer to go off at a specified interval
    00377     in the future (LAZY_FLUSH_INTERVAL_IN_SECONDS).
    00378
    00379 Arguments:
    00380
    00381     None
    00382
    00383 Return Value:
    00384
    00385     None.
    00386
    00387 --*/
    00388
    00389 {
    00390     LARGE_INTEGER DueTime;
    00391
    00392     PAGED_CODE();
    00393     CMLOG(CML_FLOW, CMS_IO) {
    00394         KdPrint(("CmpLazyFlush: setting lazy flush timer\n"));
    00395     }
    00396     if (!CmpNoWrite) {
    00397
    00398         DueTime.QuadPart = Int32x32To64(LAZY_FLUSH_INTERVAL_IN_SECONDS,
    00399                                         - SECOND_MULT);
    00400
    00401         //
    00402         // Indicate relative time
    00403         //
    00404
    00405         KeSetTimer(&CmpLazyFlushTimer,
    00406                    DueTime,
    00407                    &CmpLazyFlushDpc);
    00408
    00409     }
    00410
    00411
    00412 }

NTSTATUS CmpLinkHiveToMaster | ( | PUNICODE_STRING | LinkName,
|  | HANDLE | RootDirectory,
|  | PCMHIVE | CmHive,
|  | BOOLEAN | Allocate,
|  | PSECURITY_DESCRIPTOR | SecurityDescriptor
| ) |

Definition at line 1421 of file cmsysini.c.

Referenced by CmInitSystem1(), CmLoadKey(), CmpInitializeHiveList(), CmpInitializeSystemHive(), and CmpLoadHiveVolatile().

    01430                    :
    01431
    01432     The existing, "free floating" hive CmHive describes is linked into
    01433     the name space at the node named by LinkName.  The node will be created.
    01434     The hive is assumed to already have an appropriate root node.
    01435
    01436 Arguments:
    01437
    01438     LinkName - supplies a pointer to a unicode string which describes where
    01439                 in the registry name space the hive is to be linked.
    01440                 All components but the last must exist.  The last must not.
    01441
    01442     RootDirectory - Supplies the handle the LinkName is relative to.
    01443
    01444     CmHive - pointer to a CMHIVE structure describing the hive to link in.
    01445
    01446     Allocate - TRUE indicates that the root cell is to be created
    01447                FALSE indicates the root cell already exists.
    01448
    01449     SecurityDescriptor - supplies a pointer to the security descriptor to
    01450                be placed on the hive root.
    01451
    01452 Return Value:
    01453
    01454     TRUE == success, FALSE == failure
    01455
    01456 --*/
    01457 {
    01458     OBJECT_ATTRIBUTES   ObjectAttributes;
    01459     HANDLE              KeyHandle;
    01460     CM_PARSE_CONTEXT    ParseContext;
    01461     NTSTATUS            Status;
    01462     PCM_KEY_BODY        KeyBody;
    01463
    01464     PAGED_CODE();
    01465     //
    01466     // Fill in special ParseContext to indicate that we are creating
    01467     // a link node and opening or creating a root node.
    01468     //
    01469     ParseContext.TitleIndex = 0;
    01470     ParseContext.Class.Length = 0;
    01471     ParseContext.Class.MaximumLength = 0;
    01472     ParseContext.Class.Buffer = NULL;
    01473     ParseContext.CreateOptions = 0;
    01474     ParseContext.CreateLink = TRUE;
    01475     ParseContext.ChildHive.KeyHive = &CmHive->Hive;
    01476     if (Allocate) {
    01477
    01478         //
    01479         // Creating a new root node
    01480         //
    01481
    01482         ParseContext.ChildHive.KeyCell = HCELL_NIL;
    01483     } else {
    01484
    01485         //
    01486         // Opening an existing root node
    01487         //
    01488
    01489         ParseContext.ChildHive.KeyCell = CmHive->Hive.BaseBlock->RootCell;
    01490     }
    01491
    01492     //
    01493     // Create a path to the hive
    01494     //
    01495     InitializeObjectAttributes(
    01496         &ObjectAttributes,
    01497         LinkName,
    01498         OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
    01499         (HANDLE)RootDirectory,
    01500         SecurityDescriptor
    01501         );
    01502
    01503     Status = ObOpenObjectByName( &ObjectAttributes,
    01504                                  CmpKeyObjectType,
    01505                                  KernelMode,
    01506                                  NULL,
    01507                                  KEY_READ | KEY_WRITE,
    01508                                  (PVOID)&ParseContext,
    01509                                  &KeyHandle );
    01510
    01511     if (!NT_SUCCESS(Status)) {
    01512         CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
    01513             KdPrint(("CmpLinkHiveToMaster: "));
    01514             KdPrint(("ObOpenObjectByName() failed %08lx\n", Status));
    01515             KdPrint(("\tLinkName='%ws'\n", LinkName));
    01516         }
    01517         return Status;
    01518     }
    01519
    01520     //
    01521     // Report the notification event
    01522     //
    01523     Status = ObReferenceObjectByHandle(KeyHandle,
    01524                                        0,
    01525                                        CmpKeyObjectType,
    01526                                        KernelMode,
    01527                                        (PVOID *)&KeyBody,
    01528                                        NULL);
    01529     ASSERT(NT_SUCCESS(Status));
    01530     if (NT_SUCCESS(Status)) {
    01531         CmpReportNotify(KeyBody->KeyControlBlock,
    01532                         KeyBody->KeyControlBlock->KeyHive,
    01533                         KeyBody->KeyControlBlock->KeyCell,
    01534                         REG_NOTIFY_CHANGE_NAME);
    01535
    01536         ObDereferenceObject((PVOID)KeyBody);
    01537     }
    01538
    01539     ZwClose(KeyHandle);
    01540     return STATUS_SUCCESS;
    01541 }

VOID CmpLockRegistry | ( | VOID |  | ) |

Definition at line 44 of file cmsubs3.c.

Referenced by CmEnumerateKey(), CmEnumerateValueKey(), CmpCloseKeyObject(), CmpDeleteKeyObject(), CmpLazyFlushWorker(), CmpQueryKeyName(), CmpSecurityMethod(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), CmSetValueKey(), NtFlushKey(), NtNotifyChangeMultipleKeys(), and NtOpenKey().

    00049                    :
    00050
    00051     Lock the registry for shared (read-only) access
    00052
    00053 Arguments:
    00054
    00055     None.
    00056
    00057 Return Value:
    00058
    00059     None, the registry lock will be held for shared access upon return.
    00060
    00061 --*/
    00062 {
    00063     #if DBG
    00064     PVOID       Caller;
    00065     PVOID       CallerCaller;
    00066     #endif
    00067
    00068     KeEnterCriticalRegion();
    00069     ExAcquireResourceShared(&CmpRegistryLock, TRUE);
    00070
    00071     #if DBG
    00072     RtlGetCallersAddress(&Caller, &CallerCaller);
    00073     CMLOG(CML_FLOW, CMS_LOCKING) {
    00074         KdPrint(("CmpLockRegistry: c, cc: %08lx  %08lx\n", Caller, CallerCaller));
    00075     }
    00076     #endif
    00077
    00078 }

VOID CmpLockRegistryExclusive | ( | VOID |  | ) |

Definition at line 81 of file cmsubs3.c.

References CmpCaller, CmpCallerCaller, CmpRegistryLock, ExAcquireResourceExclusive, KeEnterCriticalRegion, RtlGetCallersAddress(), Status, and TRUE.

Referenced by CmDeleteKey(), CmDeleteValueKey(), CmGetSystemDriverList(), CmInitSystem1(), CmNotifyRunDown(), CmpCloneControlSet(), CmpCloneHwProfile(), CmpFileSetSize(), CmpInitHiveFromFile(), CmpLoadHiveVolatile(), CmpRefreshHive(), CmpSaveBootControlSet(), CmpSaveKeyByFileCopy(), CmpSecurityMethod(), CmReplaceKey(), CmRestoreKey(), CmSaveKey(), CmSaveMergedKeys(), CmSetLastWriteTimeKey(), CmSetValueKey(), CmShutdownSystem(), CmUnloadKey(), NtCreateKey(), NtInitializeRegistry(), NtNotifyChangeMultipleKeys(), NtQueryOpenSubKeys(), and NtUnloadKey().

    00086                    :
    00087
    00088     Lock the registry for exclusive (write) access.
    00089
    00090 Arguments:
    00091
    00092     CanWait - Supplies whether or not the call should wait
    00093               for the resource or return immediately.
    00094
    00095               If CanWait is TRUE, this will always return
    00096               TRUE.
    00097
    00098 Return Value:
    00099
    00100     TRUE - Lock was acquired exclusively
    00101
    00102     FALSE - Lock is owned by another thread.
    00103
    00104 --*/
    00105 {
    00106     BOOLEAN Status;
    00107
    00108
    00109     KeEnterCriticalRegion();
    00110     ExAcquireResourceExclusive(&CmpRegistryLock,TRUE);
    00111
    00112     RtlGetCallersAddress(&CmpCaller, &CmpCallerCaller);
    00113 }

BOOLEAN CmpMarkIndexDirty | ( | PHHIVE | Hive,
|  | HCELL_INDEX | ParentKey,
|  | HCELL_INDEX | TargetKey
| ) |

Definition at line 1608 of file cmindex.c.

References _HHIVE::Allocate, ASSERT, CM_KEY_FAST_LEAF, CM_KEY_INDEX_LEAF, CM_KEY_INDEX_ROOT, CmpCompressedNameSize(), CmpCopyCompressedName(), CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), ErrorExit(), FALSE, _CM_KEY_NODE::Flags, _HHIVE::Free, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, HvIsCellAllocated(), HvMarkCellDirty(), Index, KEY_COMP_NAME, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NULL, _HHIVE::StorageTypeCount, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, and _CM_KEY_NODE::WorkVar.

Referenced by CmpMarkKeyDirty(), and CmpMarkKeyParentDirty().

    01615                    :
    01616
    01617     Mark as dirty relevent cells of a subkey index.  The Leaf that
    01618     points to TargetKey, and the Root index block, if applicable,
    01619     will be marked dirty.  This call assumes we are setting up
    01620     for a subkey delete.
    01621
    01622 Arguments:
    01623
    01624     Hive - pointer to hive control structure for hive of interest
    01625
    01626     ParentKey - key from whose subkey list delete is to be performed
    01627
    01628     TargetKey - key being deleted
    01629
    01630 Return Value:
    01631
    01632     TRUE - it worked, FALSE - it didn't, some resource problem
    01633
    01634 --*/
    01635 {
    01636     PCM_KEY_NODE    pcell;
    01637     ULONG           i;
    01638     HCELL_INDEX     IndexCell;
    01639     PCM_KEY_INDEX   Index;
    01640     HCELL_INDEX     Child = HCELL_NIL;
    01641     UNICODE_STRING  SearchName;
    01642     BOOLEAN         IsCompressed;
    01643
    01644     pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
    01645     if (pcell->Flags & KEY_COMP_NAME) {
    01646         IsCompressed = TRUE;
    01647         SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
    01648         SearchName.MaximumLength = SearchName.Length;
    01649         SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE);
    01650         if (SearchName.Buffer==NULL) {
    01651             return(FALSE);
    01652         }
    01653         CmpCopyCompressedName(SearchName.Buffer,
    01654                               SearchName.MaximumLength,
    01655                               pcell->Name,
    01656                               pcell->NameLength);
    01657     } else {
    01658         IsCompressed = FALSE;
    01659         SearchName.Length = pcell->NameLength;
    01660         SearchName.MaximumLength = pcell->NameLength;
    01661         SearchName.Buffer = &(pcell->Name[0]);
    01662     }
    01663
    01664     pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
    01665
    01666     for (i = 0; i < Hive->StorageTypeCount; i++) {
    01667         if (pcell->SubKeyCounts[i] != 0) {
    01668             ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[i]));
    01669             IndexCell = pcell->SubKeyLists[i];
    01670             Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
    01671
    01672             if (Index->Signature == CM_KEY_INDEX_ROOT) {
    01673
    01674                 //
    01675                 // target even in index?
    01676                 //
    01677                 CmpFindSubKeyInRoot(Hive, Index, &SearchName, &Child);
    01678                 if (Child == HCELL_NIL) {
    01679                     continue;
    01680                 }
    01681
    01682                 //
    01683                 // mark root dirty
    01684                 //
    01685                 if (! HvMarkCellDirty(Hive, IndexCell)) {
    01686                     goto ErrorExit;
    01687                 }
    01688
    01689                 IndexCell = Child;
    01690                 Index = (PCM_KEY_INDEX)HvGetCell(Hive, Child);
    01691             }
    01692             ASSERT((Index->Signature == CM_KEY_INDEX_LEAF) ||
    01693                    (Index->Signature == CM_KEY_FAST_LEAF));
    01694
    01695             CmpFindSubKeyInLeaf(Hive, Index, pcell->WorkVar, &SearchName, &Child);
    01696             if (Child != HCELL_NIL) {
    01697                 if (IsCompressed) {
    01698                     (Hive->Free)(SearchName.Buffer, SearchName.Length);
    01699                 }
    01700                 return(HvMarkCellDirty(Hive, IndexCell));
    01701             }
    01702         }
    01703     }
    01704
    01705 ErrorExit:
    01706     if (IsCompressed) {
    01707         (Hive->Free)(SearchName.Buffer, SearchName.Length);
    01708     }
    01709     return FALSE;
    01710 }

BOOLEAN CmpMarkKeyDirty | ( | PHHIVE | Hive,
|  | HCELL_INDEX | Cell
| ) |

Definition at line 245 of file cmtredel.c.

References ASSERT, _CM_KEY_SECURITY::Blink, Cell, _CM_KEY_NODE::Class, CmpIsHKeyValueSmall, CmpMarkIndexDirty(), _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, FALSE, _CM_KEY_NODE::Flags, _CM_KEY_SECURITY::Flink, HCELL_NIL, Hive, HvGetCell, HvMarkCellDirty(), KEY_HIVE_ENTRY, KEY_HIVE_EXIT, KEY_PREDEF_HANDLE, _CELL_DATA::_u::KeyList, _CELL_DATA::_u::KeyNode, _CELL_DATA::_u::KeySecurity, _CELL_DATA::_u::KeyValue, _CHILD_LIST::List, _CM_KEY_NODE::Parent, _CM_KEY_NODE::Security, Stable, _CM_KEY_NODE::SubKeyCounts, TRUE, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmpFreeKeyByCell().

    00251                    :
    00252
    00253     Mark all of the cells related to a key being deleted dirty.
    00254     Includes the parent, the parent's child list, the key body,
    00255     class, security, all value entry bodies, and all of their data cells.
    00256
    00257 Arguments:
    00258
    00259     Hive - pointer to hive control structure for hive of interest
    00260
    00261     Cell - index for cell holding keybody to make dirty
    00262
    00263 Return Value:
    00264
    00265     TRUE - it worked
    00266
    00267     FALSE - some error, most likely cannot get log space
    00268
    00269 --*/
    00270 {
    00271     PCELL_DATA  ptarget;
    00272     PCELL_DATA  plist;
    00273     PCELL_DATA  security;
    00274     PCELL_DATA  pvalue;
    00275     ULONG       i;
    00276     ULONG realsize;
    00277
    00278
    00279     //
    00280     // Map in the target
    00281     //
    00282     ptarget = HvGetCell(Hive, Cell);
    00283     ASSERT(ptarget->u.KeyNode.SubKeyCounts[Stable] == 0);
    00284     ASSERT(ptarget->u.KeyNode.SubKeyCounts[Volatile] == 0);
    00285
    00286     if (ptarget->u.KeyNode.Flags & KEY_HIVE_EXIT) {
    00287
    00288         //
    00289         // If this is a link node, we are done.  Link nodes never have
    00290         // classes, values, subkeys, or security descriptors.  Since
    00291         // they always reside in the master hive, they're always volatile.
    00292         //
    00293         return(TRUE);
    00294     }
    00295
    00296     //
    00297     // mark cell itself
    00298     //
    00299     if (! HvMarkCellDirty(Hive, Cell)) {
    00300         return FALSE;
    00301     }
    00302
    00303     //
    00304     // Mark the class
    00305     //
    00306     if (ptarget->u.KeyNode.Class != HCELL_NIL) {
    00307         if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Class)) {
    00308             return FALSE;
    00309         }
    00310     }
    00311
    00312     //
    00313     // Mark security
    00314     //
    00315     if (ptarget->u.KeyNode.Security != HCELL_NIL) {
    00316         if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Security)) {
    00317             return FALSE;
    00318         }
    00319
    00320         security = HvGetCell(Hive, ptarget->u.KeyNode.Security);
    00321         if (! (HvMarkCellDirty(Hive, security->u.KeySecurity.Flink) &&
    00322                HvMarkCellDirty(Hive, security->u.KeySecurity.Blink)))
    00323         {
    00324             return FALSE;
    00325         }
    00326     }
    00327
    00328     //
    00329     // Mark the value entries and their data
    00330     //
    00331     if ( !(ptarget->u.KeyNode.Flags & KEY_PREDEF_HANDLE) &&
    00332                   (ptarget->u.KeyNode.ValueList.Count > 0)
    00333            ) {
    00334
    00335         // target list
    00336         if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.ValueList.List)) {
    00337             return FALSE;
    00338         }
    00339         plist = HvGetCell(Hive, ptarget->u.KeyNode.ValueList.List);
    00340
    00341         for (i = 0; i < ptarget->u.KeyNode.ValueList.Count; i++) {
    00342             if (! HvMarkCellDirty(Hive, plist->u.KeyList[i])) {
    00343                 return FALSE;
    00344             }
    00345
    00346             pvalue = HvGetCell(Hive, plist->u.KeyList[i]);
    00347
    00348             if (!CmpIsHKeyValueSmall(realsize, pvalue->u.KeyValue.DataLength)) {
    00349                 if (! HvMarkCellDirty(Hive, pvalue->u.KeyValue.Data)) {
    00350                     return(FALSE);
    00351                 }
    00352             }
    00353         }
    00354     }
    00355
    00356     if (ptarget->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
    00357
    00358         //
    00359         // if this is an entry node, we are done.  our parent will
    00360         // be in the master hive (and thus volatile)
    00361         //
    00362         return TRUE;
    00363     }
    00364
    00365     //
    00366     // Mark the parent's Subkey list
    00367     //
    00368     if (! CmpMarkIndexDirty(Hive, ptarget->u.KeyNode.Parent, Cell)) {
    00369         return FALSE;
    00370     }
    00371
    00372     //
    00373     // Mark the parent
    00374     //
    00375     if (! HvMarkCellDirty(Hive, ptarget->u.KeyNode.Parent)) {
    00376         return FALSE;
    00377     }
    00378
    00379
    00380     return TRUE;
    00381 }
    }

USHORT CmpNameSize | ( | IN PHHIVE | Hive,
|  | IN PUNICODE_STRING | Name
| ) |

Definition at line 33 of file cmname.c.

References Hive, Name, USHORT, and _HHIVE::Version.

    00040                    :
    00041
    00042     Determines the space needed to store a given string in the registry.  May apply
    00043     any relevant compression to compute the length, but the compression used is
    00044     guaranteed to be the same as CmpCopyName.
    00045
    00046 Arguments:
    00047
    00048     Hive - supplies the hive control structure (for version checking)
    00049
    00050     Name - Supplies the unicode string to be copied into the registry.
    00051
    00052 Return Value:
    00053
    00054     The number of bytes of storage required to store this name.
    00055
    00056 --*/
    00057
    00058 {
    00059     ULONG i;
    00060
    00061     if (Hive->Version == 1) {
    00062         return(Name->Length);
    00063     }
    00064     for (i=0;i<Name->Length/sizeof(WCHAR);i++) {
    00065         if ((USHORT)Name->Buffer[i] > (UCHAR)-1) {
    00066             return(Name->Length);
    00067         }
    00068     }
    00069     return(Name->Length / sizeof(WCHAR));
    00070
    00071 }

NTSTATUS CmpNotifyChangeKey | ( | IN PCM_KEY_BODY | KeyBody,
|  | IN PCM_POST_BLOCK | PostBlock,
|  | IN ULONG | CompletionFilter,
|  | IN BOOLEAN | WatchTree,
|  | IN PVOID | Buffer,
|  | IN ULONG | BufferSize,
|  | IN PCM_POST_BLOCK | MasterPostBlock
| ) |

Definition at line 1378 of file cmnotify.c.

References APC_LEVEL, ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, CM_NOTIFY_BLOCK, CML_MINOR, CML_WORKER, CMLOG, CmpFreePostBlock(), CmpInitializeKeyNameString(), CmpPostNotify(), CMS_NOTIFY, CMS_POOL, ExAllocatePool, ExAllocatePoolWithQuotaTag, ExFreePool(), FALSE, _CM_NOTIFY_BLOCK::Filter, Hive, HiveList, _CM_NOTIFY_BLOCK::HiveList, IsMasterPostBlock, KeLowerIrql(), KeRaiseIrql(), _CM_NOTIFY_BLOCK::KeyBody, _CM_NOTIFY_BLOCK::KeyControlBlock, KeyName, MAX_KEY_NAME_LENGTH, _CM_NOTIFY_BLOCK::NotifyPending, NULL, PAGED_CODE, PagedPool, POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, _CM_NOTIFY_BLOCK::PostList, PsGetCurrentThread, SeCaptureSubjectContext(), _CM_NOTIFY_BLOCK::SubjectContext, _CM_KEY_CONTROL_BLOCK::TotalLevels, TRUE, _CM_NOTIFY_BLOCK::WatchTree, and WatchTree.

Referenced by NtNotifyChangeMultipleKeys().

    01389                    :
    01390
    01391     This routine sets up the NotifyBlock, and attaches the PostBlock
    01392     to it.  When it returns, the Notify is visible to the system,
    01393     and will receive event reports.
    01394
    01395     If there is already an event report pending, then the notify
    01396     call will be satisified at once.
    01397
    01398 Arguments:
    01399
    01400     KeyBody - pointer to key object that handle refers to, allows access
    01401               to key control block, notify block, etc.
    01402
    01403     PostBlock - pointer to structure that describes how/where the caller
    01404                 is to be notified.
    01405
    01406                 WARNING:    PostBlock must come from Pool, THIS routine
    01407                             will keep it, back side will free it.  This
    01408                             routine WILL free it in case of error.
    01409
    01410     CompletionFilter - what types of events the caller wants to see
    01411
    01412     WatchTree - TRUE to watch whole subtree, FALSE to watch only immediate
    01413                 key the notify is applied to
    01414
    01415     Buffer - pointer to area to recieve notify data
    01416
    01417     BufferSize - size of buffer, also size user would like to allocate
    01418                  for internal buffer
    01419
    01420     MasterPostBlock - the post block of the master notification. Used to
    01421                       insert the PostBlock into the CancelPostList list.
    01422
    01423 Return Value:
    01424
    01425     Status.
    01426
    01427 --*/
    01428 {
    01429     PCM_NOTIFY_BLOCK    NotifyBlock;
    01430     PCM_NOTIFY_BLOCK    node;
    01431     PLIST_ENTRY         ptr;
    01432     PCMHIVE             Hive;
    01433     KIRQL               OldIrql;
    01434
    01435     PAGED_CODE();
    01436     CMLOG(CML_WORKER, CMS_NOTIFY) {
    01437         KdPrint(("CmpNotifyChangeKey:\n"));
    01438         KdPrint(("\tKeyBody:%08lx PostBlock:%08lx ", KeyBody, PostBlock));
    01439         KdPrint(("Filter:%08lx WatchTree:%08lx\n", CompletionFilter, WatchTree));
    01440 #if DBG
    01441         if(PostBlock->TraceIntoDebugger) {
    01442             WCHAR                   *NameBuffer = NULL;
    01443             UNICODE_STRING          KeyName;
    01444
    01445             KdPrint(("[CM]CmpNotifyChangeKey: PostBlock:%08lx\tMasterBlock: %08lx\n", PostBlock,MasterPostBlock));
    01446             NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    01447             if(NameBuffer&&KeyBody->KeyControlBlock->KeyNode) {
    01448                CmpInitializeKeyNameString(KeyBody->KeyControlBlock->KeyNode,&KeyName,NameBuffer);
    01449                KdPrint(("\t[CM]CmpNotifyChangeKey: Key = %.*S\n",KeyName.Length / sizeof(WCHAR),KeyName.Buffer));
    01450                ExFreePool(NameBuffer);
    01451             }
    01452         }
    01453 #endif
    01454     }
    01455
    01456     //
    01457     // The registry lock should be aquired exclusively by the caller !!!
    01458     //
    01459     ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    01460
    01461     if (KeyBody->KeyControlBlock->Delete) {
    01462 #ifdef KCB_TO_KEYBODY_LINK
    01463         ASSERT( KeyBody->NotifyBlock == NULL );
    01464 #endif
    01465         CmpFreePostBlock(PostBlock);
    01466         return STATUS_KEY_DELETED;
    01467     }
    01468
    01469     Hive = (PCMHIVE)KeyBody->KeyControlBlock->KeyHive;
    01470     Hive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    01471     NotifyBlock = KeyBody->NotifyBlock;
    01472
    01473     if (NotifyBlock == NULL) {
    01474         //
    01475         // Set up new notify session
    01476         //
    01477         NotifyBlock = ExAllocatePoolWithQuotaTag(PagedPool|POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,sizeof(CM_NOTIFY_BLOCK),CM_NOTIFYBLOCK_TAG);
    01478         CMLOG(CML_MINOR, CMS_POOL) {
    01479             KdPrint(("**CmpNotifyChangeKey: allocate:%08lx, ", sizeof(CM_NOTIFY_BLOCK)));
    01480             KdPrint(("type:%d, at:%08lx\n", PagedPool, NotifyBlock));
    01481         }
    01482
    01483         if (NotifyBlock == NULL) {
    01484             CmpFreePostBlock(PostBlock);
    01485             return STATUS_INSUFFICIENT_RESOURCES;
    01486         }
    01487         NotifyBlock->KeyControlBlock = KeyBody->KeyControlBlock;
    01488         NotifyBlock->Filter = CompletionFilter;
    01489         NotifyBlock->WatchTree = WatchTree;
    01490         NotifyBlock->NotifyPending = FALSE;
    01491         InitializeListHead(&(NotifyBlock->PostList));
    01492         KeyBody->NotifyBlock = NotifyBlock;
    01493         NotifyBlock->KeyBody = KeyBody;
    01494         ASSERT( KeyBody->KeyControlBlock->Delete == FALSE );
    01495
    01496         CMLOG(CML_WORKER, CMS_NOTIFY) {
    01497 #if DBG
    01498             if(PostBlock->TraceIntoDebugger) {
    01499                 WCHAR                   *NameBuffer = NULL;
    01500                 UNICODE_STRING          KeyName;
    01501
    01502                 NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    01503                 if(NameBuffer) {
    01504                    CmpInitializeKeyNameString(KeyBody->KeyControlBlock->KeyNode,&KeyName,NameBuffer);
    01505                    KdPrint(("[CM]\tCmpNotifyChangeKey: New NotifyBlock at:%08lx was allocated for Key = %.*S\n",NotifyBlock,KeyName.Length / sizeof(WCHAR),KeyName.Buffer));
    01506                    ExFreePool(NameBuffer);
    01507                 }
    01508             }
    01509 #endif
    01510         }
    01511
    01512         //
    01513         // IMPLEMENTATION NOTE:
    01514         //      If we ever want to actually return the buffers full of
    01515         //      data, the buffer should be allocated and its address
    01516         //      stored in the notify block here.
    01517         //
    01518
    01519         //
    01520         // Capture the subject context so we can do checking once the
    01521         // notify goes off.
    01522         //
    01523         SeCaptureSubjectContext(&NotifyBlock->SubjectContext);
    01524
    01525         //
    01526         // Attach notify block to hive in properly sorted order
    01527         //
    01528         ptr = &(Hive->NotifyList);
    01529         while (TRUE) {
    01530             if (ptr->Flink == NULL) {
    01531                 //
    01532                 // End of list, add self after ptr.
    01533                 //
    01534                 ptr->Flink = &(NotifyBlock->HiveList);
    01535                 NotifyBlock->HiveList.Flink = NULL;
    01536                 NotifyBlock->HiveList.Blink = ptr;
    01537                 break;
    01538             }
    01539
    01540             ptr = ptr->Flink;
    01541
    01542             node = CONTAINING_RECORD(ptr, CM_NOTIFY_BLOCK, HiveList);
    01543
    01544             if (node->KeyControlBlock->TotalLevels >
    01545                 KeyBody->KeyControlBlock->TotalLevels)
    01546             {
    01547                 //
    01548                 // ptr -> notify with longer name than us, insert in FRONT
    01549                 //
    01550                 NotifyBlock->HiveList.Flink = ptr;
    01551                 ptr->Blink->Flink = &(NotifyBlock->HiveList);
    01552                 NotifyBlock->HiveList.Blink = ptr->Blink;
    01553                 ptr->Blink = &(NotifyBlock->HiveList);
    01554                 break;
    01555             }
    01556         }
    01557     }
    01558
    01559
    01560     //
    01561     // Add post block to front of notify block's list, and add it to thread list.
    01562     //
    01563     InsertHeadList(
    01564         &(NotifyBlock->PostList),
    01565         &(PostBlock->NotifyList)
    01566         );
    01567
    01568
    01569
    01570     if( IsMasterPostBlock(PostBlock) ) {
    01571         //
    01572         // Protect against outrageous calls
    01573         //
    01574         ASSERT(PostBlock == MasterPostBlock);
    01575
    01576         //
    01577         // When the notification is a master one, initialize the CancelPostList list
    01578         //
    01579         InitializeListHead(&(PostBlock->CancelPostList));
    01580     } else {
    01581         //
    01582         // Add PostBlock at the end of the CancelPostList list from the master post
    01583         //
    01584         InsertTailList(
    01585             &(MasterPostBlock->CancelPostList),
    01586             &(PostBlock->CancelPostList)
    01587             );
    01588     }
    01589
    01590
    01591     KeRaiseIrql(APC_LEVEL, &OldIrql);
    01592     InsertHeadList(
    01593         &(PsGetCurrentThread()->PostBlockList),
    01594         &(PostBlock->ThreadList)
    01595         );
    01596
    01597     CMLOG(CML_WORKER, CMS_NOTIFY) {
    01598 #if DBG
    01599         if(PostBlock->TraceIntoDebugger) {
    01600             KdPrint(("[CM]\tCmpNotifyChangeKey: Attaching the post:%08lx\t to thread:%08lx\n",PostBlock,PsGetCurrentThread()));
    01601         }
    01602 #endif
    01603     }
    01604
    01605     KeLowerIrql(OldIrql);
    01606
    01607     //
    01608     // If there is a notify pending (will not be if we just created
    01609     // the notify block) then post it at once.  Note that this call
    01610     // ALWAYS returns STATUS_PENDING unless it fails.  Caller must
    01611     // ALWAYS look in IoStatusBlock to see what happened.
    01612     //
    01613     if (NotifyBlock->NotifyPending == TRUE) {
    01614         CmpPostNotify(
    01615             NotifyBlock,
    01616             NULL,
    01617             0,
    01618             STATUS_NOTIFY_ENUM_DIR,
    01619             NULL
    01620             );
    01621         //
    01622         // return STATUS_SUCCESS to signal to the caller the the notify already been triggered
    01623         //
    01624         return STATUS_SUCCESS;
    01625     }
    01626
    01627     //
    01628     // return STATUS_PENDING to signal to the caller the the notify has not been triggered yet
    01629     //
    01630     return STATUS_PENDING;
    01631 }

NTSTATUS CmpOpenHiveFiles | ( | PUNICODE_STRING | BaseName,
|  | PWSTR Extension | OPTIONAL,
|  | PHANDLE | Primary,
|  | PHANDLE | Secondary,
|  | PULONG | PrimaryDisposition,
|  | PULONG | SecondaryDispoition,
|  | BOOLEAN | CreateAllowed,
|  | BOOLEAN | MarkAsSystemHive,
|  | PULONG | ClusterSize
| ) |

| Referenced by CmpInitHiveFromFile(), CmpInitializeHiveList(), EhOpenHive(), and MyCmpInitHiveFromFile().

NTSTATUS 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
| ) |

Definition at line 145 of file cmparse.c.

References Cell, CM_HASH_STACK_SIZE, CM_KCB_CACHE_MASK, CM_KCB_KEY_NON_EXIST, CM_KCB_NO_SUBKEY, CM_KCB_SUBKEY_ONE, CM_SUBKEY_HINT_LENGTH, CML_FLOW, CML_MAJOR, CML_MINOR, CMLOG, CMP_PARSE_GOTO_CREATE, CMP_PARSE_GOTO_NONE, CMP_PARSE_GOTO_RETURN, CMP_PARSE_GOTO_RETURN2, CmpAddInfoAfterParseFailure(), CmpCacheLookup(), CmpComputeHashValue(), CmpCreateKeyControlBlock(), CmpCreateLinkNode(), CmpDereferenceKeyControlBlock(), CmpDereferenceKeyControlBlockWithLock(), CmpDoCreate(), CmpDoOpen(), CmpFindSubKeyByName(), CmpGetNextName(), CmpGetSymbolicLink(), CmpKeyObjectType, CmpMasterHive, CmpNoMasterCreates, CmpReferenceKeyControlBlock(), CmpRemoveKeyControlBlock(), CmpStepThroughExit, CMS_PARSE, _CM_PARSE_CONTEXT::CreateLink, _CM_PARSE_CONTEXT::Disposition, FALSE, HCELL_INDEX, HCELL_NIL, Hive, _CMHIVE::Hive, HvGetCell, Index, kcb(), KEY_SYM_LINK, _CM_KEY_CONTROL_BLOCK::KeyCell, _CM_KEY_CONTROL_BLOCK::KeyHive, _CM_KEY_CONTROL_BLOCK::KeyNode, LOCK_KCB_TREE, NT_SUCCESS, NTSTATUS(), NULL, PHCELL_INDEX, RtlUpcaseUnicodeChar(), TRUE, UNLOCK_KCB_TREE, and USHORT.

Referenced by CmpCreateObjectTypes().

    00159                    :
    00160
    00161     This routine interfaces to the NT Object Manager.  It is invoked when
    00162     the object system is given the name of an entity to create or open and
    00163     a Key or KeyRoot is encountered in the path.  In practice this means
    00164     that this routine is called for all objects whose names are of the
    00165     form \REGISTRY\...
    00166
    00167     This routine will create a Key object, which is effectively an open
    00168     instance to a registry key node, and return its address
    00169     (for the success case.)
    00170
    00171 Arguments:
    00172
    00173     ParseObject - Pointer to a KeyRoot or Key, thus -> KEY_BODY.
    00174
    00175     ObjectType - Type of the object being opened.
    00176
    00177     AccessState - Running security access state information for operation.
    00178
    00179     AccessMode - Access mode of the original caller.
    00180
    00181     Attributes - Attributes to be applied to the object.
    00182
    00183     CompleteName - Supplies complete name of the object.
    00184
    00185     RemainingName - Remaining name of the object.
    00186
    00187     Context - if create or hive root open, points to a CM_PARSE_CONTEXT
    00188               structure,
    00189               if open, is NULL.
    00190
    00191     SecurityQos - Optional security quality of service indicator.
    00192
    00193     Object - The address of a variable to receive the created key object, if
    00194         any.
    00195
    00196 Return Value:
    00197
    00198     The function return value is one of the following:
    00199
    00200         a)  Success - This indicates that the function succeeded and the object
    00201             parameter contains the address of the created key object.
    00202
    00203         b)  STATUS_REPARSE - This indicates that a symbolic link key was
    00204             found, and the path should be reparsed.
    00205
    00206         c)  Error - This indicates that the file was not found or created and
    00207             no file object was created.
    00208
    00209 --*/
    00210 {
    00211     NTSTATUS    status;
    00212     BOOLEAN     rc;
    00213     PHHIVE      Hive;
    00214     PCM_KEY_NODE Node;
    00215     HCELL_INDEX Cell;
    00216     HCELL_INDEX ParentCell;
    00217     HCELL_INDEX NextCell;
    00218     PHCELL_INDEX Index;
    00219     PCM_PARSE_CONTEXT lcontext;
    00220     UNICODE_STRING Current;
    00221     UNICODE_STRING  NextName;   // Component last returned by CmpGetNextName,
    00222                                 // will always be behind Current.
    00223     BOOLEAN     Last;           // TRUE if component NextName points to
    00224                                 // is the last one in the path.
    00225
    00226     CM_HASH_ENTRY   HashStack[CM_HASH_STACK_SIZE];
    00227     ULONG           TotalRemainingSubkeys;
    00228     ULONG           MatchRemainSubkeyLevel;
    00229     ULONG           TotalSubkeys=0;
    00230     ULONG           SubkeyParsed;
    00231     PCM_KEY_CONTROL_BLOCK   kcb;
    00232     PCM_KEY_HASH PCmpCacheEntry=NULL;
    00233     PCM_KEY_CONTROL_BLOCK   ParentKcb;
    00234     UNICODE_STRING  TmpNodeName;
    00235     ULONG   namelength;
    00236     ULONG   GoToValue = CMP_PARSE_GOTO_NONE;
    00237     BOOLEAN CompleteKeyCached = FALSE;
    00238     USHORT i,j;
    00239     WCHAR *p1;
    00240
    00241     CMLOG(CML_MINOR, CMS_PARSE) {
    00242         KdPrint(("CmpParseKey:\n\t"));
    00243         KdPrint(("CompleteName = '%wZ'\n\t", CompleteName));
    00244         KdPrint(("RemainingName = '%wZ'\n", RemainingName));
    00245     }
    00246
    00247     //
    00248     // Strip off any trailing path separators
    00249     //
    00250     while ((RemainingName->Length > 0) &&
    00251            (RemainingName->Buffer[(RemainingName->Length/sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR)) {
    00252         RemainingName->Length -= sizeof(WCHAR);
    00253     }
    00254
    00255     Current = *RemainingName;
    00256     if (ObjectType != CmpKeyObjectType) {
    00257         return STATUS_OBJECT_TYPE_MISMATCH;
    00258     }
    00259
    00260     lcontext = (PCM_PARSE_CONTEXT)Context;
    00261
    00262     //
    00263     // Check to make sure the passed in root key is not marked for deletion.
    00264     //
    00265     if (((PCM_KEY_BODY)ParseObject)->KeyControlBlock->Delete == TRUE) {
    00266         return(STATUS_KEY_DELETED);
    00267     }
    00268
    00269     //
    00270     // Fetch the starting Hive.Cell.  Because of the way the parse
    00271     // paths work, this will always be defined.  (ObOpenObjectByName
    00272     // had to bounce off of a KeyObject or KeyRootObject to get here)
    00273     //
    00274     kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
    00275     Hive = kcb->KeyHive;
    00276     Cell = kcb->KeyCell;
    00277     Node = kcb->KeyNode;
    00278
    00279     //
    00280     // Compute the hash values of each subkeys
    00281     //
    00282     TotalRemainingSubkeys = CmpComputeHashValue(HashStack,
    00283                                                 &TotalSubkeys,
    00284                                                 kcb->ConvKey,
    00285                                                 &Current);
    00286
    00287
    00288     // Look up from the cache.  kcb will be changed if we find a partial or exact match
    00289     // PCmpCacheEntry, the entry found, will be move to the front of
    00290     // the Cache.
    00291
    00292     LOCK_KCB_TREE();
    00293
    00294     status = CmpCacheLookup(HashStack,
    00295                             TotalRemainingSubkeys,
    00296                             &MatchRemainSubkeyLevel,
    00297                             &kcb,
    00298                             &Current,
    00299                             &Hive,
    00300                             &Cell);
    00301     //
    00302     // The RefCount of kcb was increased in the CmpCacheLookup process,
    00303     // It is to protect it from being kicked out of cache.
    00304     // Make sure we dereference it after we are done.
    00305     //
    00306
    00307     //
    00308     // First make sure it is OK to proceed.
    00309     //
    00310     if (!NT_SUCCESS (status)) {
    00311         UNLOCK_KCB_TREE();
    00312         goto JustReturn;
    00313     }
    00314
    00315     SubkeyParsed = MatchRemainSubkeyLevel;
    00316     ParentKcb = kcb;
    00317
    00318     //
    00319     // First check if there are further information in the cached kcb.
    00320     //
    00321     // The additional information can be
    00322     // 1. This cached key is a fake key (CM_KCB_KEY_NON_EXIST), then either let it be created
    00323     //    or return STATUS_OBJECT_NAME_NOT_FOUND.
    00324     // 2. The cached key is not the destination and it has no subkey (CM_KCB_NO_SUBKEY).
    00325     // 3. The cached key is not the destination and it has
    00326     //    the first four characters of its subkeys.  If the flag is CM_KCB_SUBKEY_ONE, there is only one subkey
    00327     //    and the four char is embedded in the KCB.  If the flag is CM_KCB_SUBKEY_INFO, then there is
    00328     //    an allocation for these info.
    00329     //
    00330     // We do need to lock KCB tree to protect the KCB being modified.  Currently there is not lock contention problem
    00331     // on KCBs, We can change KCB lock to a read-write lock if this becomes a problem.
    00332     //
    00333
    00334     if (kcb->ExtFlags & CM_KCB_CACHE_MASK) {
    00335         if (MatchRemainSubkeyLevel == TotalRemainingSubkeys) {
    00336             //
    00337             // We have found a cache for the complete path,
    00338             //
    00339             if (kcb->ExtFlags & CM_KCB_KEY_NON_EXIST) {
    00340                 //
    00341                 // This key does not exist.
    00342                 //
    00343                 if (ARGUMENT_PRESENT(lcontext)) {
    00344                     ULONG LevelToSkip = TotalRemainingSubkeys-1;
    00345                     ULONG i=0;
    00346                     //
    00347                     // The non-existing key is the desination key and lcontext is present.
    00348                     // delete this fake kcb and let the real one be created.
    00349                     //
    00350                     // Temporarily increase the RefCount of the ParentKcb so it's
    00351                     // not removed while removing the fake and creating the real KCB.
    00352                     //
    00353
    00354                     ParentKcb = kcb->ParentKcb;
    00355
    00356                     if (CmpReferenceKeyControlBlock(ParentKcb)) {
    00357
    00358                         kcb->Delete = TRUE;
    00359                         CmpRemoveKeyControlBlock(kcb);
    00360                         CmpDereferenceKeyControlBlockWithLock(kcb);
    00361
    00362                         //
    00363                         // Update Hive, Cell and Node
    00364                         //
    00365                         Hive = ParentKcb->KeyHive;
    00366                         Cell = ParentKcb->KeyCell;
    00367                         Node = ParentKcb->KeyNode;
    00368
    00369                         //
    00370                         // Now get the child name to be created.
    00371                         //
    00372
    00373                         NextName = *RemainingName;
    00374                         if ((NextName.Buffer == NULL) || (NextName.Length == 0)) {
    00375                             KdPrint(("Something wrong in finding the child name\n"));
    00376                             DbgBreakPoint();
    00377                         }
    00378                         //
    00379                         // Skip over leading path separators
    00380                         //
    00381                         if (*(NextName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
    00382                             NextName.Buffer++;
    00383                             NextName.Length -= sizeof(WCHAR);
    00384                             NextName.MaximumLength -= sizeof(WCHAR);
    00385                         }
    00386
    00387                         while (i < LevelToSkip) {
    00388                             if (*(NextName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
    00389                                 i++;
    00390                             }
    00391                             NextName.Buffer++;
    00392                             NextName.Length -= sizeof(WCHAR);
    00393                             NextName.MaximumLength -= sizeof(WCHAR);
    00394                         }
    00395                         GoToValue = CMP_PARSE_GOTO_CREATE;
    00396                     } else {
    00397                         //
    00398                         // We have maxed the RefCount of ParentKcb; treate it as key cannot be created.
    00399                         // The ParentKcb will not be dereferenced at the end.
    00400                         //
    00401                         status = STATUS_INSUFFICIENT_RESOURCES;
    00402                         GoToValue = CMP_PARSE_GOTO_RETURN2;
    00403                     }
    00404                 } else {
    00405                     status = STATUS_OBJECT_NAME_NOT_FOUND;
    00406                     GoToValue = CMP_PARSE_GOTO_RETURN;
    00407                 }
    00408             }
    00409         } else if (kcb->ExtFlags & CM_KCB_KEY_NON_EXIST) {
    00410             //
    00411             // one subkey (not desination) in the path does not exist. no point to continue.
    00412             //
    00413             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00414             GoToValue = CMP_PARSE_GOTO_RETURN;
    00415         } else if (kcb->ExtFlags & CM_KCB_NO_SUBKEY) {
    00416             //
    00417             // one parent in the path has no subkey. see if it is a create.
    00418             //
    00419             if (((TotalRemainingSubkeys - MatchRemainSubkeyLevel) == 1) && (ARGUMENT_PRESENT(lcontext))) {
    00420                 //
    00421                 // Now we are going to create this subkey.
    00422                 // The kcb cache will be updated in CmpDoCreate routine.
    00423                 //
    00424             } else {
    00425                 status = STATUS_OBJECT_NAME_NOT_FOUND;
    00426                 GoToValue = CMP_PARSE_GOTO_RETURN;
    00427             }
    00428         } else {
    00429             //
    00430             // We have a partial match.  Current is the remaining name to be parsed.
    00431             // The Key has either one or a few subkeys and has index hint. check if it is the candidate.
    00432             //
    00433             ULONG HintLength;
    00434             ULONG HintCounts;
    00435             ULONG CmpCount;
    00436             WCHAR c1;
    00437             WCHAR c2;
    00438             UCHAR *TmpName;
    00439             LONG Result;
    00440             BOOLEAN NoMatch = TRUE;
    00441             //
    00442             // When NoMatch is TRUE, we know for sure there is no subkey that can match.
    00443             // When NoMatch is FALSE, it can we either we found a match or
    00444             // there is not enough information.  Either case, we need to continue
    00445             // the parse.
    00446             //
    00447
    00448             TmpNodeName = Current;
    00449
    00450             rc = CmpGetNextName(&TmpNodeName, &NextName, &Last);
    00451
    00452             if (kcb->ExtFlags & CM_KCB_SUBKEY_ONE) {
    00453                 HintCounts = 1;
    00454                 TmpName = &(kcb->NameHint[0]);
    00455             } else {
    00456                 //
    00457                 // More than one child, the hint info in not inside the kcb but pointed by kcb.
    00458                 //
    00459                 HintCounts = kcb->IndexHint->Count;
    00460                 TmpName = &(kcb->IndexHint->NameHint[0]);
    00461             }
    00462
    00463             //
    00464             // use the hint to predict if there is a possible match
    00465             //
    00466             if (NextName.Length < (sizeof(WCHAR) * CM_SUBKEY_HINT_LENGTH) ) {
    00467                 HintLength = NextName.Length / sizeof(WCHAR);
    00468             } else {
    00469                 HintLength = CM_SUBKEY_HINT_LENGTH;
    00470             }
    00471
    00472             for (CmpCount=0; CmpCount<HintCounts; CmpCount++) {
    00473                 NoMatch = FALSE;
    00474
    00475                 if( TmpName[0] == 0) {
    00476                     //
    00477                     // No hint available; assume the subkey exist and go on with the parse
    00478                     //
    00479                     break;
    00480                 }
    00481
    00482                 for (i=0; i<HintLength; i++) {
    00483                     c1 = NextName.Buffer[i];
    00484                     c2 = (WCHAR) *TmpName;
    00485
    00486                     Result = (LONG)RtlUpcaseUnicodeChar(c1) - (LONG)RtlUpcaseUnicodeChar(c2);
    00487                     if (Result != 0) {
    00488                         NoMatch = TRUE;
    00489                         TmpName += (CM_SUBKEY_HINT_LENGTH-i);
    00490                         break;
    00491                     }
    00492                     TmpName++;
    00493                 }
    00494
    00495                 if (NoMatch == FALSE) {
    00496                     //
    00497                     // There is a match.
    00498                     //
    00499                     break;
    00500                 }
    00501             }
    00502
    00503             if (NoMatch) {
    00504                 if (((TotalRemainingSubkeys - MatchRemainSubkeyLevel) == 1) && (ARGUMENT_PRESENT(lcontext))) {
    00505                     //
    00506                     // No we are going to create this subkey.
    00507                     // The kcb cache will be updated in CmpDoCreate.
    00508                     //
    00509                 } else {
    00510                     status = STATUS_OBJECT_NAME_NOT_FOUND;
    00511                     GoToValue = CMP_PARSE_GOTO_RETURN;
    00512                 }
    00513             }
    00514         }
    00515     }
    00516
    00517     UNLOCK_KCB_TREE();
    00518
    00519
    00520     if (GoToValue == CMP_PARSE_GOTO_CREATE) {
    00521         goto CreateChild;
    00522     } else if (GoToValue == CMP_PARSE_GOTO_RETURN) {
    00523         goto FreeAndReturn;
    00524     } else if (GoToValue == CMP_PARSE_GOTO_RETURN2) {
    00525         goto JustReturn;
    00526     }
    00527
    00528     if (MatchRemainSubkeyLevel) {
    00529         // Found something, update the information to start the search
    00530         // from the new BaseName
    00531
    00532         //
    00533         // Get the Node address from the kcb.
    00534         // (Always try to utilize the KCB to avoid touching the registry data).
    00535         //
    00536         Node = kcb->KeyNode;
    00537
    00538         if (MatchRemainSubkeyLevel == TotalSubkeys) {
    00539             // The complete key has been found in the cache,
    00540             // go directly to the CmpDoOpen.
    00541
    00542             //
    00543             // Found the whole thing cached.
    00544             //
    00545             //
    00546             CompleteKeyCached = TRUE;
    00547             goto Found;
    00548         }
    00549     } else if (TotalRemainingSubkeys == 0) {
    00550         //
    00551         // BUGBUG John Vert (jvert) 10/7/1997
    00552         //
    00553         CompleteKeyCached = TRUE;
    00554         goto Found;
    00555     }
    00556
    00557     //
    00558     // Parse the path.
    00559     //
    00560
    00561     status = STATUS_SUCCESS;
    00562     while (TRUE) {
    00563
    00564         //
    00565         // Parse out next component of name
    00566         //
    00567         rc = CmpGetNextName(&Current, &NextName, &Last);
    00568         if ((NextName.Length > 0) && (rc == TRUE)) {
    00569
    00570             //
    00571             // As we iterate through, we will create a kcb for each subkey parsed.
    00572             //
    00573             // Always use the information in kcb to avoid
    00574             // touching registry data.
    00575             //
    00576             if (!(kcb->KeyNode->Flags & KEY_SYM_LINK)) {
    00577                 //
    00578                 // Got a legal name component, see if we can find a sub key
    00579                 // that actually has such a name.
    00580                 //
    00581                 NextCell = CmpFindSubKeyByName(Hive,
    00582                                                Node,
    00583                                                &NextName);
    00584
    00585                 CMLOG(CML_FLOW, CMS_PARSE) {
    00586                     KdPrint(("CmpParseKey:\n\t"));
    00587                     KdPrint(("NextName = '%wZ'\n\t", &NextName));
    00588                     KdPrint(("NextCell = %08lx  Last = %01lx\n", NextCell, Last));
    00589                 }
    00590                 if (NextCell != HCELL_NIL) {
    00591                     Cell = NextCell;
    00592                     Node = (PCM_KEY_NODE)HvGetCell(Hive,Cell);
    00593                     if (Last == TRUE) {
    00594
    00595 Found:
    00596                         //
    00597                         // We will open the key regardless of whether the
    00598                         // call was open or create, so step through exit
    00599                         // portholes here.
    00600                         //
    00601
    00602                         if (CompleteKeyCached == TRUE) {
    00603                             //
    00604                             // If the key found is already cached,
    00605                             // do not need to StepThroughExit
    00606                             // (no kcb is created using exit node).
    00607                             // This prevents us from touching the key node just for the Flags.
    00608                             //
    00609                         } else {
    00610                             CmpStepThroughExit(Hive, Cell, Node);
    00611                         }
    00612                         //
    00613                         // We have found the entire path, so we want to open
    00614                         // it (for both Open and Create calls).
    00615                         // Hive,Cell -> the key we are supposed to open.
    00616                         //
    00617
    00618                         status = CmpDoOpen(Hive,
    00619                                            Cell,
    00620                                            Node,
    00621                                            AccessState,
    00622                                            AccessMode,
    00623                                            Attributes,
    00624                                            lcontext,
    00625                                            CompleteKeyCached,
    00626                                            &kcb,
    00627                                            &NextName,
    00628                                            Object);
    00629
    00630                         if (status == STATUS_REPARSE) {
    00631                             //
    00632                             // The given key was a symbolic link.  Find the name of
    00633                             // its link, and return STATUS_REPARSE to the Object Manager.
    00634                             //
    00635
    00636                             if (!CmpGetSymbolicLink(Hive,
    00637                                                     Node,
    00638                                                     CompleteName,
    00639                                                     kcb,
    00640                                                     NULL)) {
    00641                                 CMLOG(CML_MAJOR, CMS_PARSE) {
    00642                                     KdPrint(("CmpParseKey: couldn't find symbolic link name\n"));
    00643                                 }
    00644                                 status = STATUS_OBJECT_NAME_NOT_FOUND;
    00645                             }
    00646                         }
    00647
    00648                         break;
    00649                     }
    00650                     // else
    00651                     //   Not at end, so we'll simply iterate and consume
    00652                     //   the next component.
    00653                     //
    00654                     //
    00655                     // Step through exit portholes here.
    00656                     // This ensures that no KCB is created using
    00657                     // the Exit node.
    00658                     //
    00659
    00660                     CmpStepThroughExit(Hive, Cell, Node);
    00661
    00662                     //
    00663                     // Create a kcb for each subkey parsed.
    00664                     //
    00665
    00666                     kcb = CmpCreateKeyControlBlock(Hive,
    00667                                                    Cell,
    00668                                                    Node,
    00669                                                    ParentKcb,
    00670                                                    FALSE,
    00671                                                    &NextName);
    00672
    00673                     if (kcb  == NULL) {
    00674                         status = STATUS_INSUFFICIENT_RESOURCES;
    00675                         goto FreeAndReturn;
    00676                         //
    00677                         // Currently, the kcb has one extra reference conut to be decremented.
    00678                         // So, remember it so we can dereference it properly.
    00679                         //
    00680                     }
    00681                     //
    00682                     // Now we have created a kcb for the next level,
    00683                     // the kcb in the previous level is no longer needed.
    00684                     // Dereference the parent kcb.
    00685                     //
    00686                     CmpDereferenceKeyControlBlock(ParentKcb);
    00687
    00688                     ParentKcb = kcb;
    00689
    00690
    00691                 } else {
    00692                     //
    00693                     // We did not find a key matching the name, but no
    00694                     // unexpected error occured
    00695                     //
    00696
    00697                     if ((Last == TRUE) && (ARGUMENT_PRESENT(lcontext))) {
    00698
    00699 CreateChild:
    00700                         //
    00701                         // Only unfound component is last one, and operation
    00702                         // is a create, so perform the create.
    00703                         //
    00704
    00705                         //
    00706                         // There are two possibilities here.  The normal one
    00707                         // is that we are simply creating a new node.
    00708                         //
    00709                         // The abnormal one is that we are creating a root
    00710                         // node that is linked to the main hive.  In this
    00711                         // case, we must create the link.  Once the link is
    00712                         // created, we can check to see if the root node
    00713                         // exists, then either create it or open it as
    00714                         // necessary.
    00715                         //
    00716                         // CmpCreateLinkNode creates the link, and calls
    00717                         // back to CmpDoCreate or CmpDoOpen to create or open
    00718                         // the root node as appropriate.
    00719                         //
    00720
    00721                         if (lcontext->CreateLink) {
    00722                             status = CmpCreateLinkNode(Hive,
    00723                                                        Cell,
    00724                                                        AccessState,
    00725                                                        NextName,
    00726                                                        AccessMode,
    00727                                                        Attributes,
    00728                                                        lcontext,
    00729                                                        ParentKcb,
    00730                                                        Object);
    00731
    00732                         } else {
    00733
    00734                             if ( (Hive == &(CmpMasterHive->Hive)) &&
    00735                                  (CmpNoMasterCreates == TRUE) ) {
    00736                                 //
    00737                                 // attempting to create a cell in the master
    00738                                 // hive, and not a link, so blow out of here,
    00739                                 // since it wouldn't work anyway.
    00740                                 //
    00741                                 status = STATUS_INVALID_PARAMETER;
    00742                                 break;
    00743                             }
    00744
    00745                             status = CmpDoCreate(Hive,
    00746                                                  Cell,
    00747                                                  AccessState,
    00748                                                  &NextName,
    00749                                                  AccessMode,
    00750                                                  lcontext,
    00751                                                  ParentKcb,
    00752                                                  Object);
    00753                         }
    00754
    00755                         lcontext->Disposition = REG_CREATED_NEW_KEY;
    00756                         break;
    00757
    00758                     } else {
    00759
    00760                         //
    00761                         // Did not find a key to match the component, and
    00762                         // are not at the end of the path.  Thus, open must
    00763                         // fail because the whole path dosn't exist, create must
    00764                         // fail because more than 1 component doesn't exist.
    00765                         //
    00766                         //
    00767                         // We have a lookup failure here, so having additional information
    00768                         // about this kcb may help us not to go through all the code just to fail again.
    00769                         //
    00770                         ParentKcb = CmpAddInfoAfterParseFailure(Hive,
    00771                                                                 Cell,
    00772                                                                 Node,
    00773                                                                 kcb,
    00774                                                                 &NextName
    00775                                                                 );
    00776
    00777                         status = STATUS_OBJECT_NAME_NOT_FOUND;
    00778                         break;
    00779                     }
    00780
    00781                 }
    00782
    00783             } else {
    00784                 //
    00785                 // The given key was a symbolic link.  Find the name of
    00786                 // its link, and return STATUS_REPARSE to the Object Manager.
    00787                 //
    00788                 Current.Buffer = NextName.Buffer;
    00789                 Current.Length += NextName.Length;
    00790                 Current.MaximumLength += NextName.MaximumLength;
    00791                 if (CmpGetSymbolicLink(Hive,
    00792                                        Node,
    00793                                        CompleteName,
    00794                                        kcb,
    00795                                        &Current)) {
    00796
    00797                     status = STATUS_REPARSE;
    00798                     break;
    00799
    00800                 } else {
    00801                     CMLOG(CML_MAJOR, CMS_PARSE) {
    00802                         KdPrint(("CmpParseKey: couldn't find symbolic link name\n"));
    00803                     }
    00804                     status = STATUS_OBJECT_NAME_NOT_FOUND;
    00805                     break;
    00806                 }
    00807             }
    00808
    00809         } else if (rc == TRUE && Last == TRUE) {
    00810             //
    00811             // We will open the \Registry root.
    00812             // Or some strange remaining name that
    00813             // screw up the lookup.
    00814             //
    00815             CmpStepThroughExit(Hive, Cell, Node);
    00816
    00817             //
    00818             // We have found the entire path, so we want to open
    00819             // it (for both Open and Create calls).
    00820             // Hive,Cell -> the key we are supposed to open.
    00821             //
    00822             status = CmpDoOpen(Hive,
    00823                                Cell,
    00824                                Node,
    00825                                AccessState,
    00826                                AccessMode,
    00827                                Attributes,
    00828                                lcontext,
    00829                                TRUE,
    00830                                &kcb,
    00831                                &NextName,
    00832                                Object);
    00833             break;
    00834
    00835         } else {
    00836
    00837             //
    00838             // bogus path -> fail
    00839             //
    00840             status = STATUS_INVALID_PARAMETER;
    00841             break;
    00842         }
    00843
    00844     } // while
    00845
    00846 FreeAndReturn:
    00847     //
    00848     // Now we have to free the last kcb that still has one extra reference count to
    00849     // protect it from being freed.
    00850     //
    00851
    00852     CmpDereferenceKeyControlBlock(ParentKcb);
    00853 JustReturn:
    00854
    00855     return status;
    00856 }

VOID CmpPostApc | ( | struct _KAPC * | Apc,
|  | PKNORMAL_ROUTINE * | NormalRoutine,
|  | PVOID * | NormalContext,
|  | PVOID * | SystemArgument1,
|  | PVOID * | SystemArgument2
| ) |

Definition at line 804 of file cmnotify.c.

References _CM_POST_BLOCK_UNION::AsyncUser, CML_MAJOR, CMLOG, CmpCheckPostBlock, CmpFreePostBlock(), CmpFreeSlavePost(), CmpRemoveEntryList, CmpSetIoStatus, CMS_NOTIFY, EXCEPTION_EXECUTE_HANDLER, FALSE, _CM_ASYNC_USER_POST_BLOCK::IoStatusBlock, KeSetEvent(), L, NULL, ObDereferenceObject, PAGED_CODE, PsGetCurrentProcess, _CM_POST_BLOCK::ThreadList, _CM_POST_BLOCK::u, and _CM_ASYNC_USER_POST_BLOCK::UserEvent.

Referenced by NtNotifyChangeMultipleKeys().

    00813                    :
    00814
    00815     This is the kernel apc routine.  It is called for all notifies,
    00816     regardless of what form of notification the caller requested.
    00817
    00818     We compute the postblock address from the apc object address.
    00819     IoStatus is set.  SystemEvent and UserEvent will be signalled
    00820     as appropriate.  If the user requested an APC, then NormalRoutine
    00821     will be set at entry and executed when we exit.  The PostBlock
    00822     is freed here.
    00823
    00824 Arguments:
    00825
    00826     Apc - pointer to apc object
    00827
    00828     NormalRoutine - Will be called when we return
    00829
    00830     NormalContext - will be 1st argument to normal routine, ApcContext
    00831                     passed in when NtNotifyChangeKey was called
    00832
    00833     SystemArgument1 -  IN: Status value for IoStatusBlock
    00834                       OUT: Ptr to IoStatusBlock (2nd arg to user apc routine)
    00835
    00836     SystemArgument2 - Pointer to the PostBlock
    00837
    00838 Return Value:
    00839
    00840     NONE.
    00841
    00842 --*/
    00843 {
    00844     PCM_POST_BLOCK  PostBlock;
    00845
    00846     PAGED_CODE();
    00847     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00848         KdPrint(("CmpPostApc:\n"));
    00849         KdPrint(("\tApc:%08lx ", Apc));
    00850         KdPrint(("NormalRoutine:%08lx\n", NormalRoutine));
    00851         KdPrint(("\tNormalContext:%08lx", NormalContext));
    00852         KdPrint(("\tSystemArgument1=IoStatusBlock:%08lx\n", SystemArgument1));
    00853     }
    00854
    00855
    00856     PostBlock = *(PCM_POST_BLOCK *)SystemArgument2;
    00857
    00858     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00859 #if DBG
    00860         if(PostBlock->TraceIntoDebugger) {
    00861             KdPrint(("[CM]CmpPostApc: PostBlock:%08lx\n", PostBlock));
    00862         }
    00863 #endif
    00864     }
    00865     //
    00866     // Fill in IO Status Block
    00867     //
    00868     // IMPLEMENTATION NOTE:
    00869     //      If we ever want to actually implement the code that returns
    00870     //      names of things that changed, this is the place to copy the
    00871     //      buffer into the caller's buffer.
    00872     //
    00873     //  Sundown only: Use a 32bit IO_STATUS_BLOCK if the caller is 32bit.
    00874
    00875     try {
    00876         CmpSetIoStatus(PostBlock->u->AsyncUser.IoStatusBlock,
    00877                        *((ULONG *)SystemArgument1),
    00878                        0L,
    00879                        PsGetCurrentProcess()->Wow64Process != NULL);
    00880     } except (EXCEPTION_EXECUTE_HANDLER) {
    00881         NOTHING;
    00882     }
    00883     *SystemArgument1 = PostBlock->u->AsyncUser.IoStatusBlock;
    00884
    00885     //
    00886     // This is an Async notify, do all work here, including
    00887     // cleaning up the post block
    00888     //
    00889
    00890     //
    00891     // Signal UserEvent if present, and deref it.
    00892     //
    00893     if (PostBlock->u->AsyncUser.UserEvent != NULL) {
    00894         KeSetEvent(PostBlock->u->AsyncUser.UserEvent,
    00895                    0,
    00896                    FALSE);
    00897         ObDereferenceObject(PostBlock->u->AsyncUser.UserEvent);
    00898     }
    00899
    00900     //
    00901     // remove the post block from the thread list, and free it
    00902     //
    00903     // Use Cmp variant to protect for multiple deletion of the same object
    00904     CmpRemoveEntryList(&(PostBlock->ThreadList));
    00905
    00906     // debug only checks
    00907     CmpCheckPostBlock(PostBlock);
    00908     //
    00909         // Free the slave post block to avoid "dangling" postblocks
    00910         //
    00911         CmpFreeSlavePost(PostBlock);
    00912     //
    00913         // free this post block
    00914         //
    00915         CmpFreePostBlock(PostBlock);
    00916
    00917     return;
    00918 }

VOID CmpPostApcRunDown | ( | struct _KAPC * | Apc | ) |

Definition at line 922 of file cmnotify.c.

References APC_LEVEL, _CM_POST_BLOCK_UNION::AsyncUser, CML_MAJOR, CMLOG, CmpFreePostBlock(), CmpFreeSlavePost(), CmpRemoveEntryList, CmpSetIoStatus, CMS_NOTIFY, EXCEPTION_EXECUTE_HANDLER, FALSE, _CM_ASYNC_USER_POST_BLOCK::IoStatusBlock, KeLowerIrql(), KeRaiseIrql(), KeSetEvent(), L, NULL, ObDereferenceObject, PAGED_CODE, PsGetCurrentProcess, _KAPC::SystemArgument2, _CM_POST_BLOCK::ThreadList, _CM_POST_BLOCK::u, and _CM_ASYNC_USER_POST_BLOCK::UserEvent.

Referenced by NtNotifyChangeMultipleKeys().

    00927                    :
    00928
    00929     This routine is called to clear away apcs in the apc queue
    00930     of a thread that has been terminated.
    00931
    00932     Since the apc is in the apc queue, we know that it is NOT in
    00933     any NotifyBlock's post list.  It is, however, in the threads's
    00934     PostBlockList.
    00935
    00936     Therefore, poke any user events so that waiters are not stuck,
    00937     drop the references so the event can be cleaned up, delist the
    00938     PostBlock and free it.
    00939
    00940     Since we are cleaning up the thread, SystemEvents are not interesting.
    00941
    00942     Since the apc is in the apc queue, we know that if there were any other
    00943     notifications related to this one, they are cleaned up by the
    00944     CmPostNotify routine
    00945
    00946 Arguments:
    00947
    00948     Apc - pointer to apc object
    00949
    00950 Return Value:
    00951
    00952     NONE.
    00953
    00954 --*/
    00955 {
    00956     PCM_POST_BLOCK  PostBlock;
    00957     KIRQL           OldIrql;
    00958
    00959     PAGED_CODE();
    00960     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00961         KdPrint(("CmpApcRunDown:"));
    00962         KdPrint(("\tApc:%08lx \n", Apc));
    00963     }
    00964
    00965     KeRaiseIrql(APC_LEVEL, &OldIrql);
    00966
    00967     PostBlock = (PCM_POST_BLOCK)Apc->SystemArgument2;
    00968
    00969     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00970 #if DBG
    00971         if(PostBlock->TraceIntoDebugger) {
    00972             KdPrint(("[CM]CmpPostApcRunDown: PostBlock:%08lx\n", PostBlock));
    00973         }
    00974 #endif
    00975     }
    00976
    00977     //
    00978     // report status and wake up any threads that might otherwise
    00979     // be stuck.  also drop any event references we hold
    00980     //
    00981     //  Sundown only: Use a 32bit IO_STATUS_BLOCK if the caller is 32bit.
    00982
    00983     try {
    00984         CmpSetIoStatus(PostBlock->u->AsyncUser.IoStatusBlock,
    00985                        STATUS_NOTIFY_CLEANUP,
    00986                        0L,
    00987                        PsGetCurrentProcess()->Wow64Process != NULL);
    00988     } except (EXCEPTION_EXECUTE_HANDLER) {
    00989         NOTHING;
    00990     }
    00991
    00992     if (PostBlock->u->AsyncUser.UserEvent != NULL) {
    00993         KeSetEvent(
    00994             PostBlock->u->AsyncUser.UserEvent,
    00995             0,
    00996             FALSE
    00997             );
    00998         ObDereferenceObject(PostBlock->u->AsyncUser.UserEvent);
    00999     }
    01000
    01001     //
    01002     // delist the post block
    01003     //
    01004     // Use Cmp variant to protect for multiple deletion of the same object
    01005     CmpRemoveEntryList(&(PostBlock->ThreadList));
    01006
    01007         //
    01008         // Free the slave post block to avoid "dangling" postblocks
    01009         //
    01010         CmpFreeSlavePost(PostBlock);
    01011     //
    01012     // Free the post block.  Use Ex call because PostBlocks are NOT
    01013     // part of the global registry pool computation, but are instead
    01014     // part of NonPagedPool with Quota.
    01015     //
    01016     CmpFreePostBlock(PostBlock);
    01017
    01018     KeLowerIrql(OldIrql);
    01019
    01020     return;
    01021 }

VOID CmpPostNotify | ( | PCM_NOTIFY_BLOCK | NotifyBlock,
|  | PUNICODE_STRING Name | OPTIONAL,
|  | ULONG | Filter,
|  | NTSTATUS | Status,
|  | PLIST_ENTRY ExternalKeyDeref | OPTIONAL
| ) |

Definition at line 487 of file cmnotify.c.

References _CM_ASYNC_USER_POST_BLOCK::Apc, APC_LEVEL, ASSERT, ASSERT_CM_LOCK_OWNED, _CM_POST_BLOCK_UNION::AsyncUser, _CM_POST_BLOCK::CancelPostList, ClearMasterPostBlockFlag, CML_MAJOR, CMLOG, CmpAddToDelayedDeref(), CmpCancelSlavePost(), CmpClearListEntry, CmpDelayedDerefKeys(), CmpFreePostBlock(), CmpInitializeKeyNameString(), CmpRemoveEntryList, CMS_NOTIFY, ExAllocatePool, ExFreePool(), ExQueueWorkItem(), FALSE, Filter, IsMasterPostBlock, KeInsertQueueApc(), KeLowerIrql(), KeRaiseIrql(), KeSetEvent(), _CM_NOTIFY_BLOCK::KeyControlBlock, KeyName, _CM_KEY_CONTROL_BLOCK::KeyNode, LOCK_POST_LIST, MAX_KEY_NAME_LENGTH, Name, _CM_POST_BLOCK::NotifyList, _CM_NOTIFY_BLOCK::NotifyPending, _CM_POST_BLOCK::NotifyType, NULL, ObDereferenceObject, PAGED_CODE, PagedPool, PostAsyncKernel, PostAsyncUser, PostBlockType, _CM_NOTIFY_BLOCK::PostList, PostSynchronous, SetMasterPostBlockFlag, _CM_SYNC_POST_BLOCK::Status, Status, _CM_POST_BLOCK_UNION::Sync, _CM_SYNC_POST_BLOCK::SystemEvent, _CM_POST_BLOCK::ThreadList, TRUE, _CM_POST_BLOCK::u, and UNLOCK_POST_LIST.

Referenced by CmpCloseKeyObject(), CmpFlushNotify(), CmpNotifyChangeKey(), and CmpReportNotifyHelper().

    00496                    :
    00497
    00498     Actually report the notify event by signalling events, enqueing
    00499     APCs, and so forth.
    00500
    00501     When Status is STATUS_NOTIFY_CLEANUP:
    00502
    00503       - if the post block is a slave one, just cancel it.
    00504       - if the post block is a master one, cancel all slave post blocks
    00505         and trigger event on the master block.
    00506
    00507 Comments:
    00508
    00509     This routine is using a "delayed dereferencing" technique to prevent
    00510     deadlocks that may appear when a keybody is dereferenced while holding
    00511     the post block lock. As for this, a list with keybodies that have to be
    00512     dereferenced is constructed while walking the list of postblocks attached
    00513     to the current notify block and the related (slave or master) post blocks.
    00514     The list is built by tricking postblocks. For all postblock about to be
    00515     freed the PostKeyBody member is added to the local list and then set to NULL
    00516     on the postblock. This will avoid the key body dereferencing in CmpFreePostBlock.
    00517     Instead, after the postblock lock is released, the local list is iterated and
    00518     the keybodies are dereferenced and the storage for associated CM_POST_KEY_BODY
    00519     objects is freed.
    00520
    00521
    00522 Arguments:
    00523
    00524     NotifyBlock - pointer to structure that describes the notify
    00525                   operation.  (Where to post to)
    00526
    00527     Name - name of key at which event occurred.
    00528
    00529     Filter - nature of event
    00530
    00531     Status - completion status to report
    00532
    00533     ExternalKeyDeref - this parameter (when not NULL) specifies that the caller doesn't
    00534                     want any keybody to be dereferenced while in this routine
    00535
    00536 Return Value:
    00537
    00538     NONE.
    00539
    00540 --*/
    00541 {
    00542     PCM_POST_BLOCK      PostBlock;
    00543     PCM_POST_BLOCK      SlavePostBlock;
    00544     LIST_ENTRY          LocalDelayedDeref;
    00545     KIRQL               OldIrql;
    00546     PLIST_ENTRY         DelayedDeref;
    00547
    00548     Filter;
    00549     Name;
    00550
    00551     PAGED_CODE();
    00552     CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00553         KdPrint(("CmpPostNotify:\n"));
    00554         KdPrint(("\tNotifyBlock:%08lx  ", NotifyBlock));
    00555         KdPrint(("\tName = %wZ\n", Name));
    00556         KdPrint(("\tFilter:%08lx  Status=%08lx\n", Filter, Status));
    00557     }
    00558     ASSERT_CM_LOCK_OWNED();
    00559
    00560     if( ARGUMENT_PRESENT(ExternalKeyDeref) ) {
    00561         //
    00562         // The caller want to do all keybody dereferencing by himself
    00563         //
    00564         DelayedDeref = ExternalKeyDeref;
    00565     } else {
    00566         // local delayed dereferencing (the caller doesn't care!)
    00567         DelayedDeref = &LocalDelayedDeref;
    00568         InitializeListHead(DelayedDeref);
    00569     }
    00570
    00571     //
    00572     // Aquire exclusive access over the postlist(s)
    00573     //
    00574     LOCK_POST_LIST();
    00575
    00576     if (IsListEmpty(&(NotifyBlock->PostList)) == TRUE) {
    00577         //
    00578         // Nothing to post, set a mark and return
    00579         //
    00580         NotifyBlock->NotifyPending = TRUE;
    00581         UNLOCK_POST_LIST();
    00582         return;
    00583     }
    00584     NotifyBlock->NotifyPending = FALSE;
    00585
    00586     //
    00587     // IMPLEMENTATION NOTE:
    00588     //      If we ever want to actually implement the code that returns
    00589     //      names of things that changed, this is the place to add the
    00590     //      name and operation type to the buffer.
    00591     //
    00592
    00593     //
    00594     // Pull and post all the entries in the post list
    00595     //
    00596     while (IsListEmpty(&(NotifyBlock->PostList)) == FALSE) {
    00597
    00598         //
    00599         // Remove from the notify block list, and enqueue the apc.
    00600         // The apc will remove itself from the thread list
    00601         //
    00602         PostBlock = (PCM_POST_BLOCK)RemoveHeadList(&(NotifyBlock->PostList));
    00603         PostBlock = CONTAINING_RECORD(PostBlock,
    00604                                       CM_POST_BLOCK,
    00605                                       NotifyList);
    00606
    00607         // Protect for multiple deletion of the same object
    00608         CmpClearListEntry(&(PostBlock->NotifyList));
    00609
    00610         CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00611 #if DBG
    00612             if(PostBlock->TraceIntoDebugger) {
    00613                 WCHAR                   *NameBuffer = NULL;
    00614                 UNICODE_STRING          KeyName;
    00615
    00616                 NameBuffer = ExAllocatePool(PagedPool, MAX_KEY_NAME_LENGTH);
    00617                 if(NameBuffer) {
    00618                    CmpInitializeKeyNameString(NotifyBlock->KeyControlBlock->KeyNode,&KeyName,NameBuffer);
    00619                    KdPrint(("[CM]CmpPostNotify: NotifyBlock:%08lx\tKey = %.*S\n",NotifyBlock,KeyName.Length / sizeof(WCHAR),KeyName.Buffer));
    00620                    ExFreePool(NameBuffer);
    00621                 }
    00622                 KdPrint(("[CM]\tCmpPostNotify: PostBlock:%08lx\n", PostBlock));
    00623             }
    00624 #endif
    00625         }
    00626
    00627         if( (Status == STATUS_NOTIFY_CLEANUP) && !IsMasterPostBlock(PostBlock) ) {
    00628             //
    00629             // Cleanup notification (i.e. the key handle was closed or the key was deleted)
    00630             // When the post is a slave one, just cancel it. Canceling means:
    00631             //      1. Removing from the notify PostList (aldready done at this point - see above)
    00632             //      2. Unchaining from the Master Block CancelPostList
    00633             //      3. Delisting from the thread PostBlockList
    00634             //      4. Actually freeing the memory
    00635             //
    00636
    00637             // Use Cmp variant to protect for multiple deletion of the same object
    00638             CmpRemoveEntryList(&(PostBlock->CancelPostList));
    00639             //
    00640             // FIX 289351
    00641             //
    00642             // Use Cmp variant to protect for multiple deletion of the same object
    00643             KeRaiseIrql(APC_LEVEL, &OldIrql);
    00644             CmpRemoveEntryList(&(PostBlock->ThreadList));
    00645             KeLowerIrql(OldIrql);
    00646
    00647             if( PostBlock->NotifyType != PostSynchronous ) {
    00648
    00649                 // add to the deref list and clean the post block
    00650                 CmpAddToDelayedDeref(PostBlock,DelayedDeref);
    00651
    00652                 //
    00653                 // Front-end routine will do self cleanup for syncrounous notifications
    00654                 CmpFreePostBlock(PostBlock);
    00655             }
    00656
    00657             CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00658 #if DBG
    00659                 if(PostBlock->TraceIntoDebugger) {
    00660                     KdPrint(("[CM]\tCmpPostNotify: PostBlock:%08lx is a slave block,and notify is CLEANUP==> just cleanning\n", PostBlock));
    00661                 }
    00662 #endif
    00663             }
    00664
    00665             continue; //try the next one
    00666         }
    00667
    00668         //
    00669         // Simulate that this block is the master one, so we can free the others
    00670         // Doing that will ensure the right memory dealocation when the master
    00671         // (from now on this block) will be freed.
    00672         //
    00673         if(!IsMasterPostBlock(PostBlock)) {
    00674             //
    00675             // oops.,this is not the master block, we have some more work to do
    00676             //
    00677             SlavePostBlock = PostBlock;
    00678             do {
    00679                 SlavePostBlock = (PCM_POST_BLOCK)SlavePostBlock->CancelPostList.Flink;
    00680                 SlavePostBlock = CONTAINING_RECORD(SlavePostBlock,
    00681                                                    CM_POST_BLOCK,
    00682                                                    CancelPostList);
    00683                 //
    00684                 // reset the "master flag" if set
    00685                 //
    00686                 ClearMasterPostBlockFlag(SlavePostBlock);
    00687             } while (SlavePostBlock != PostBlock);
    00688
    00689             //
    00690             // Make this post block the master one
    00691             //
    00692             SetMasterPostBlockFlag(PostBlock);
    00693         }
    00694
    00695         CMLOG(CML_MAJOR, CMS_NOTIFY) {
    00696 #if DBG
    00697             if(PostBlock->TraceIntoDebugger) {
    00698                 KdPrint(("[CM]\tCmpPostNotify: Master block switched to :%08lx\n", PostBlock));
    00699             }
    00700 #endif
    00701         }
    00702
    00703         //
    00704         // Cancel all slave Post requests that may be linked to self
    00705         //
    00706
    00707         if( PostBlockType(PostBlock) != PostSynchronous ) {
    00708             //
    00709             // Front-end routine will do self cleanup for syncrounous notifications
    00710             CmpCancelSlavePost(PostBlock,DelayedDeref);
    00711             //
    00712             // Do the same for the master (in case master and slave got switched)
    00713             // This will avoid dereferencing the keybody from CmpPostApc
    00714             CmpAddToDelayedDeref(PostBlock,DelayedDeref);
    00715         }
    00716
    00717         switch (PostBlockType(PostBlock)) {
    00718             case PostSynchronous:
    00719                 //
    00720                 // This is a SYNC notify call.  There will be no user event,
    00721                 // and no user apc routine.  Quick exit here, just fill in
    00722                 // the Status and poke the event.
    00723                 //
    00724                 // Holder of the systemevent will wake up and free the
    00725                 // postblock.  If we free it here, we get a race & bugcheck.
    00726                 //
    00727                 // Set the flink to NULL so that the front side can tell this
    00728                 // has been removed if its wait aborts.
    00729                 //
    00730                 PostBlock->NotifyList.Flink = NULL;
    00731                 PostBlock->u->Sync.Status = Status;
    00732                 KeSetEvent(PostBlock->u->Sync.SystemEvent,
    00733                            0,
    00734                            FALSE);
    00735                 break;
    00736
    00737             case PostAsyncUser:
    00738                 //
    00739                 // Insert the APC into the queue
    00740                 //
    00741                 KeInsertQueueApc(PostBlock->u->AsyncUser.Apc,
    00742                                  (PVOID)ULongToPtr(Status),
    00743                                  (PVOID)PostBlock,
    00744                                  0);
    00745                 break;
    00746
    00747             case PostAsyncKernel:
    00748                 //
    00749                 // Queue the work item, then free the post block.
    00750                 //
    00751                 if (PostBlock->u->AsyncKernel.WorkItem != NULL) {
    00752                     ExQueueWorkItem(PostBlock->u->AsyncKernel.WorkItem,
    00753                                     PostBlock->u->AsyncKernel.QueueType);
    00754                 }
    00755                 //
    00756                 // Signal Event if present, and deref it.
    00757                 //
    00758                 if (PostBlock->u->AsyncKernel.Event != NULL) {
    00759                     KeSetEvent(PostBlock->u->AsyncKernel.Event,
    00760                                0,
    00761                                FALSE);
    00762                     ObDereferenceObject(PostBlock->u->AsyncKernel.Event);
    00763                 }
    00764
    00765                                 //
    00766                                 // Multiple async kernel notification are not allowed
    00767                                 //
    00768                                 ASSERT(IsListEmpty(&(PostBlock->CancelPostList)) == TRUE);
    00769                                 //
    00770                 // remove the post block from the thread list, and free it
    00771                 //
    00772                 // Use Cmp variant to protect for multiple deletion of the same object
    00773                 KeRaiseIrql(APC_LEVEL, &OldIrql);
    00774                 CmpRemoveEntryList(&(PostBlock->ThreadList));
    00775                 KeLowerIrql(OldIrql);
    00776
    00777                 // it was already added to delayed deref.
    00778                 CmpFreePostBlock(PostBlock);
    00779                 break;
    00780         }
    00781     }
    00782
    00783     UNLOCK_POST_LIST();
    00784
    00785     //
    00786     // At this point we have a list of keybody elements that have to be dereferenciated
    00787     // and the associated storage for the covering objects freed. The keybodies in this
    00788     // list have only one reference count on them (they were referenced only in
    00789     // NtNotifyChangeMultipleKeys), dereferencing them here should free the object
    00790     //
    00791
    00792     if( ARGUMENT_PRESENT(ExternalKeyDeref) ) {
    00793         // do nothing; the caller wants to handle the dereferenciation by himself!
    00794     } else {
    00795         // dereferenciate all keybodies in the delayed list
    00796         CmpDelayedDerefKeys(DelayedDeref);
    00797     }
    00798
    00799     return;
    00800 }

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

Definition at line 110 of file cmsubs2.c.

References ALIGN_OFFSET, _CM_KEY_NODE::Class, _CM_KEY_NODE::ClassLength, CmpCopyCompressedName(), CmpHKeyNameLen, _CHILD_LIST::Count, _CM_KEY_NODE::Flags, Hive, HvGetCell, KEY_COMP_NAME, _KEY_INFORMATION::KeyBasicInformation, _KEY_INFORMATION::KeyFullInformation, _KEY_INFORMATION::KeyNodeInformation, _CM_KEY_NODE::LastWriteTime, _CM_KEY_NODE::MaxClassLen, _CM_KEY_NODE::MaxNameLen, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, Name, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NTSTATUS(), Stable, _CM_KEY_NODE::SubKeyCounts, USHORT, _CM_KEY_NODE::ValueList, and Volatile.

Referenced by CmEnumerateKey(), and CmQueryKey().

    00120                    :
    00121
    00122     Do the actual copy of data for a key into caller's buffer.
    00123
    00124     If KeyInformation is not long enough to hold all requested data,
    00125     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00126     set to the number of bytes actually required.
    00127
    00128 Arguments:
    00129
    00130     Hive - supplies a pointer to the hive control structure for the hive
    00131
    00132     Node - Supplies pointer to node whose subkeys are to be found
    00133
    00134     KeyInformationClass - Specifies the type of information returned in
    00135         Buffer.  One of the following types:
    00136
    00137         KeyBasicInformation - return last write time, title index, and name.
    00138             (see KEY_BASIC_INFORMATION structure)
    00139
    00140         KeyNodeInformation - return last write time, title index, name, class.
    00141             (see KEY_NODE_INFORMATION structure)
    00142
    00143     KeyInformation -Supplies pointer to buffer to receive the data.
    00144
    00145     Length - Length of KeyInformation in bytes.
    00146
    00147     ResultLength - Number of bytes actually written into KeyInformation.
    00148
    00149 Return Value:
    00150
    00151     NTSTATUS - Result code from call, among the following:
    00152
    00153         <TBS>
    00154
    00155 --*/
    00156 {
    00157     NTSTATUS    status;
    00158     PCELL_DATA  pclass;
    00159     ULONG       requiredlength;
    00160     LONG        leftlength;
    00161     ULONG       offset;
    00162     ULONG       minimumlength;
    00163     PKEY_INFORMATION pbuffer;
    00164     USHORT      NameLength;
    00165
    00166     pbuffer = (PKEY_INFORMATION)KeyInformation;
    00167     NameLength = CmpHKeyNameLen(Node);
    00168
    00169     switch (KeyInformationClass) {
    00170
    00171     case KeyBasicInformation:
    00172
    00173         //
    00174         // LastWriteTime, TitleIndex, NameLength, Name
    00175
    00176         requiredlength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) +
    00177                          NameLength;
    00178
    00179         minimumlength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name);
    00180
    00181         *ResultLength = requiredlength;
    00182
    00183         status = STATUS_SUCCESS;
    00184
    00185         if (Length < minimumlength) {
    00186
    00187             status = STATUS_BUFFER_TOO_SMALL;
    00188
    00189         } else {
    00190
    00191             pbuffer->KeyBasicInformation.LastWriteTime =
    00192                 Node->LastWriteTime;
    00193
    00194             pbuffer->KeyBasicInformation.TitleIndex = 0;
    00195
    00196             pbuffer->KeyBasicInformation.NameLength =
    00197                 NameLength;
    00198
    00199             leftlength = Length - minimumlength;
    00200
    00201             requiredlength = NameLength;
    00202
    00203             if (leftlength < (LONG)requiredlength) {
    00204                 requiredlength = leftlength;
    00205                 status = STATUS_BUFFER_OVERFLOW;
    00206             }
    00207
    00208             if (Node->Flags & KEY_COMP_NAME) {
    00209                 CmpCopyCompressedName(pbuffer->KeyBasicInformation.Name,
    00210                                       leftlength,
    00211                                       Node->Name,
    00212                                       Node->NameLength);
    00213             } else {
    00214                 RtlCopyMemory(
    00215                     &(pbuffer->KeyBasicInformation.Name[0]),
    00216                     &(Node->Name[0]),
    00217                     requiredlength
    00218                     );
    00219             }
    00220         }
    00221
    00222         break;
    00223
    00224
    00225     case KeyNodeInformation:
    00226
    00227         //
    00228         // LastWriteTime, TitleIndex, ClassOffset, ClassLength
    00229         // NameLength, Name, Class
    00230         //
    00231         requiredlength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
    00232                          NameLength +
    00233                          Node->ClassLength;
    00234
    00235         minimumlength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
    00236
    00237         *ResultLength = requiredlength;
    00238
    00239         status = STATUS_SUCCESS;
    00240
    00241         if (Length < minimumlength) {
    00242
    00243             status = STATUS_BUFFER_TOO_SMALL;
    00244
    00245         } else {
    00246
    00247             pbuffer->KeyNodeInformation.LastWriteTime =
    00248                 Node->LastWriteTime;
    00249
    00250             pbuffer->KeyNodeInformation.TitleIndex = 0;
    00251
    00252             pbuffer->KeyNodeInformation.ClassLength =
    00253                 Node->ClassLength;
    00254
    00255             pbuffer->KeyNodeInformation.NameLength =
    00256                 NameLength;
    00257
    00258             leftlength = Length - minimumlength;
    00259             requiredlength = NameLength;
    00260
    00261             if (leftlength < (LONG)requiredlength) {
    00262                 requiredlength = leftlength;
    00263                 status = STATUS_BUFFER_OVERFLOW;
    00264             }
    00265
    00266             if (Node->Flags & KEY_COMP_NAME) {
    00267                 CmpCopyCompressedName(pbuffer->KeyNodeInformation.Name,
    00268                                       leftlength,
    00269                                       Node->Name,
    00270                                       Node->NameLength);
    00271             } else {
    00272                 RtlCopyMemory(
    00273                     &(pbuffer->KeyNodeInformation.Name[0]),
    00274                     &(Node->Name[0]),
    00275                     requiredlength
    00276                     );
    00277             }
    00278
    00279             if (Node->ClassLength > 0) {
    00280
    00281                 offset = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
    00282                             NameLength;
    00283                 offset = ALIGN_OFFSET(offset);
    00284
    00285                 pbuffer->KeyNodeInformation.ClassOffset = offset;
    00286
    00287                 pclass = HvGetCell(Hive, Node->Class);
    00288
    00289                 pbuffer = (PKEY_INFORMATION)((PUCHAR)pbuffer + offset);
    00290
    00291                 leftlength = (((LONG)Length - (LONG)offset) < 0) ?
    00292                                     0 :
    00293                                     Length - offset;
    00294
    00295                 requiredlength = Node->ClassLength;
    00296
    00297                 if (leftlength < (LONG)requiredlength) {
    00298                     requiredlength = leftlength;
    00299                     status = STATUS_BUFFER_OVERFLOW;
    00300                 }
    00301
    00302                 RtlMoveMemory(
    00303                     pbuffer,
    00304                     pclass,
    00305                     requiredlength
    00306                     );
    00307
    00308             } else {
    00309                 pbuffer->KeyNodeInformation.ClassOffset = (ULONG)-1;
    00310             }
    00311         }
    00312
    00313         break;
    00314
    00315
    00316     case KeyFullInformation:
    00317
    00318         //
    00319         // LastWriteTime, TitleIndex, ClassOffset, ClassLength,
    00320         // SubKeys, MaxNameLen, MaxClassLen, Values, MaxValueNameLen,
    00321         // MaxValueDataLen, Class
    00322         //
    00323         requiredlength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
    00324                          Node->ClassLength;
    00325
    00326         minimumlength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
    00327
    00328         *ResultLength = requiredlength;
    00329
    00330         status = STATUS_SUCCESS;
    00331
    00332         if (Length < minimumlength) {
    00333
    00334             status = STATUS_BUFFER_TOO_SMALL;
    00335
    00336         } else {
    00337
    00338             pbuffer->KeyFullInformation.LastWriteTime =
    00339                 Node->LastWriteTime;
    00340
    00341             pbuffer->KeyFullInformation.TitleIndex = 0;
    00342
    00343             pbuffer->KeyFullInformation.ClassLength =
    00344                 Node->ClassLength;
    00345
    00346             if (Node->ClassLength > 0) {
    00347
    00348                 pbuffer->KeyFullInformation.ClassOffset =
    00349                         FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
    00350
    00351                 pclass = HvGetCell(Hive, Node->Class);
    00352
    00353                 leftlength = Length - minimumlength;
    00354                 requiredlength = Node->ClassLength;
    00355
    00356                 if (leftlength < (LONG)requiredlength) {
    00357                     requiredlength = leftlength;
    00358                     status = STATUS_BUFFER_OVERFLOW;
    00359                 }
    00360
    00361                 RtlMoveMemory(
    00362                     &(pbuffer->KeyFullInformation.Class[0]),
    00363                     pclass,
    00364                     requiredlength
    00365                     );
    00366
    00367             } else {
    00368                 pbuffer->KeyFullInformation.ClassOffset = (ULONG)-1;
    00369             }
    00370
    00371             pbuffer->KeyFullInformation.SubKeys =
    00372                 Node->SubKeyCounts[Stable] +
    00373                 Node->SubKeyCounts[Volatile];
    00374
    00375             pbuffer->KeyFullInformation.Values =
    00376                 Node->ValueList.Count;
    00377
    00378             pbuffer->KeyFullInformation.MaxNameLen =
    00379                 Node->MaxNameLen;
    00380
    00381             pbuffer->KeyFullInformation.MaxClassLen =
    00382                 Node->MaxClassLen;
    00383
    00384             pbuffer->KeyFullInformation.MaxValueNameLen =
    00385                 Node->MaxValueNameLen;
    00386
    00387             pbuffer->KeyFullInformation.MaxValueDataLen =
    00388                 Node->MaxValueDataLen;
    00389
    00390         }
    00391
    00392         break;
    00393
    00394
    00395     default:
    00396         status = STATUS_INVALID_PARAMETER;
    00397         break;
    00398     }
    00399     return status;
    00400 }

NTSTATUS CmpQueryKeyName | ( | IN PVOID | Object,
|  | IN BOOLEAN | HasObjectName,
|  | OUT POBJECT_NAME_INFORMATION | ObjectNameInfo,
|  | IN ULONG | Length,
|  | OUT PULONG | ReturnLength
| ) |

Definition at line 28 of file cmquery.c.

References CML_MINOR, CMLOG, CmpConstructName(), CmpLockRegistry(), CmpUnlockRegistry(), CMS_PARSE, ExFreePoolWithTag, Name, NTSTATUS(), NULL, PROTECTED_POOL, t(), and USHORT.

Referenced by CmpCreateObjectTypes().

    00037                    :
    00038
    00039     This routine interfaces to the NT Object Manager.  It is invoked when
    00040     the object system wishes to discover the name of an object that
    00041     belongs to the registry.
    00042
    00043 Arguments:
    00044
    00045     Object - pointer to a Key, thus -> KEY_BODY.
    00046
    00047     HasObjectName - indicates whether the object manager knows about a name
    00048         for this object
    00049
    00050     ObjectNameInfo - place where we report the name
    00051
    00052     Length - maximum length they can deal with
    00053
    00054     ReturnLength - supplies variable to receive actual length
    00055
    00056 Return Value:
    00057
    00058     STATUS_SUCCESS
    00059
    00060     STATUS_INFO_LENGTH_MISMATCH
    00061
    00062 --*/
    00063
    00064 {
    00065     PUNICODE_STRING Name;
    00066     PWCHAR t;
    00067     PWCHAR s;
    00068     ULONG l;
    00069     NTSTATUS status;
    00070
    00071     UNREFERENCED_PARAMETER(HasObjectName);
    00072
    00073     CMLOG(CML_MINOR, CMS_PARSE) {
    00074         KdPrint(("CmpQueryKeyName:\n"));
    00075     }
    00076
    00077     CmpLockRegistry();
    00078
    00079     if ( ((PCM_KEY_BODY)Object)->KeyControlBlock->Delete) {
    00080         CmpUnlockRegistry();
    00081         return STATUS_KEY_DELETED;
    00082     }
    00083     Name = CmpConstructName(((PCM_KEY_BODY)Object)->KeyControlBlock);
    00084     if (Name == NULL) {
    00085         status = STATUS_INSUFFICIENT_RESOURCES;
    00086         CmpUnlockRegistry();
    00087         return status;
    00088     }
    00089
    00090     if (Length <= sizeof(OBJECT_NAME_INFORMATION)) {
    00091         *ReturnLength = Name->Length + sizeof(WCHAR) + sizeof(OBJECT_NAME_INFORMATION);
    00092         ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
    00093         CmpUnlockRegistry();
    00094         return STATUS_INFO_LENGTH_MISMATCH;  // they can't even handle null
    00095     }
    00096
    00097     t = (PWCHAR)(ObjectNameInfo + 1);
    00098     s = Name->Buffer;
    00099     l = Name->Length;
    00100     l += sizeof(WCHAR);     // account for null
    00101
    00102
    00103     *ReturnLength = l + sizeof(OBJECT_NAME_INFORMATION);
    00104     if (l > Length - sizeof(OBJECT_NAME_INFORMATION)) {
    00105         l = Length - sizeof(OBJECT_NAME_INFORMATION);
    00106         status = STATUS_INFO_LENGTH_MISMATCH;
    00107     } else {
    00108         status = STATUS_SUCCESS;
    00109     }
    00110     l -= sizeof(WCHAR);
    00111
    00112     //
    00113     // The ObjectNameInfo buffer is a usermode buffer, so make sure we have an
    00114     // exception handler in case a malicious app changes the protection out from
    00115     // under us.
    00116     //
    00117     // Note the object manager is responsible for probing the buffer and ensuring
    00118     // that a top-level exception handler returns the correct error code. We just
    00119     // need to make sure we drop our lock.
    00120     //
    00121     try {
    00122         RtlMoveMemory(t, s, l);
    00123         t[l/sizeof(WCHAR)] = UNICODE_NULL;
    00124         ObjectNameInfo->Name.Length = (USHORT)l;
    00125         ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length;
    00126         ObjectNameInfo->Name.Buffer = t;
    00127     } finally {
    00128         ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
    00129         CmpUnlockRegistry();
    00130     }
    00131     return status;
    00132 }
    }

NTSTATUS CmpQueryKeyValueData | ( | PHHIVE | Hive,
|  | PCM_CACHED_VALUE * | ContainingList,
|  | PCM_KEY_VALUE | ValueKey,
|  | BOOLEAN | ValueCached,
|  | KEY_VALUE_INFORMATION_CLASS | KeyValueInformationClass,
|  | PVOID | KeyValueInformation,
|  | ULONG | Length,
|  | PULONG | ResultLength
| ) |

VOID CmpQuotaWarningWorker | ( | IN PVOID | WorkItem | ) |

Definition at line 166 of file cmgquota.c.

References ExFreePool(), ExRaiseHardError(), NTSTATUS(), NULL, and Status.

Referenced by CmpClaimGlobalQuota().

    00172                    :
    00173
    00174     Displays hard error popup that indicates the registry quota is
    00175     running out.
    00176
    00177 Arguments:
    00178
    00179     WorkItem - Supplies pointer to the work item. This routine will
    00180                free the work item.
    00181
    00182 Return Value:
    00183
    00184     None.
    00185
    00186 --*/
    00187
    00188 {
    00189     NTSTATUS Status;
    00190     ULONG Response;
    00191
    00192     ExFreePool(WorkItem);
    00193
    00194     Status = ExRaiseHardError(STATUS_REGISTRY_QUOTA_LIMIT,
    00195                               0,
    00196                               0,
    00197                               NULL,
    00198                               OptionOk,
    00199                               &Response);
    00200 }

BOOLEAN CmpReferenceKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 345 of file cmsubs.c.

References CmpRemoveFromDelayedClose(), FALSE, _CM_KEY_CONTROL_BLOCK::RefCount, TRUE, and USHORT.

Referenced by CmpCacheLookup(), CmpCreateKeyControlBlock(), CmpDoOpen(), CmpGetSymbolicLink(), and CmpParseKey().

    00348 {
    00349     if (KeyControlBlock->RefCount == 0) {
    00350         CmpRemoveFromDelayedClose(KeyControlBlock);
    00351     }
    00352
    00353     if ((USHORT)(KeyControlBlock->RefCount + 1) == 0) {
    00354         //
    00355         // We have maxed out the ref count on this key. Probably
    00356         // some bogus app has opened the same key 64K times without
    00357         // ever closing it. Just fail the call
    00358         //
    00359         return (FALSE);
    00360     } else {
    00361         ++(KeyControlBlock->RefCount);
    00362         return (TRUE);
    00363     }
    00364 }

VOID CmpReleaseGlobalQuota | ( | IN ULONG | Size | ) |

Definition at line 265 of file cmgquota.c.

References CmpGlobalQuotaUsed, KeBugCheckEx(), and Size.

Referenced by CmpAllocate(), CmpFree(), HvFreeHivePartial(), HvInitializeHive(), and HvWriteHive().

    00270                    :
    00271
    00272     If Size <= CmpGlobalQuotaUsed, then decrement it.  Else BugCheck.
    00273
    00274 Arguments:
    00275
    00276     Size - number of bytes of GlobalQuota caller wants to release
    00277
    00278 Return Value:
    00279
    00280     NONE.
    00281
    00282 --*/
    00283 {
    00284     if (Size > CmpGlobalQuotaUsed) {
    00285         KeBugCheckEx(REGISTRY_ERROR,2,1,0,0);
    00286     }
    00287
    00288     CmpGlobalQuotaUsed -= Size;
    00289 }

VOID CmpRemoveFromDelayedClose | ( | IN PCM_KEY_CONTROL_BLOCK | kcb | ) |

Definition at line 807 of file cmsubs.c.

References ASSERT, CmpDelayedCloseSize, CmpDelayedCloseTable, CmpDelayedFreeIndex, and kcb().

Referenced by CmpCacheLookup(), CmpCreateKeyControlBlock(), CmpReferenceKeyControlBlock(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

    00810 {
    00811     ULONG i;
    00812     i = kcb->DelayedCloseIndex;
    00813
    00814     ASSERT (CmpDelayedCloseTable[i] == kcb);
    00815     ASSERT(i != CmpDelayedCloseSize);
    00816
    00817     CmpDelayedCloseTable[i] = (PCM_KEY_CONTROL_BLOCK)CmpDelayedFreeIndex;
    00818     CmpDelayedFreeIndex = i;
    00819     kcb->DelayedCloseIndex = 0;
    00820 }

VOID CmpRemoveFromHiveFileList | ( |  | ) |

| Referenced by CmpWorker().

VOID CmpRemoveKeyControlBlock | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock | ) |

Definition at line 1260 of file cmsubs.c.

References ASSERT_KCB, CmpRemoveKeyHash(), and _CM_KEY_CONTROL_BLOCK::KeyHash.

Referenced by CmDeleteKey(), CmpCacheLookup(), CmpCleanUpKcbCacheWithLock(), CmpCreateKeyControlBlock(), CmpDoCreateChild(), CmpParseKey(), CmpSearchForOpenSubKeys(), and NtUnloadKey().

    01265                    :
    01266
    01267     Remove a key control block from the KCB tree.
    01268
    01269     It is expected that no notify control blocks remain.
    01270
    01271     The kcb will NOT be freed, call DereferenceKeyControlBlock for that.
    01272
    01273     This call assumes the KCB tree is already locked or registry is locked exclusively.
    01274
    01275 Arguments:
    01276
    01277     KeyControlBlock - pointer to a key control block.
    01278
    01279 Return Value:
    01280
    01281     NONE.
    01282
    01283 --*/
    01284 {
    01285     ASSERT_KCB(KeyControlBlock);
    01286
    01287     //
    01288     // Remove the KCB from the hash table
    01289     //
    01290     CmpRemoveKeyHash(&KeyControlBlock->KeyHash);
    01291
    01292     return;
    01293 }

BOOLEAN CmpRemoveSubKey | ( | PHHIVE | Hive,
|  | HCELL_INDEX | ParentKey,
|  | HCELL_INDEX | TargetKey
| ) |

Definition at line 1714 of file cmindex.c.

References _HHIVE::Allocate, ASSERT, CM_KEY_FAST_LEAF, CM_KEY_INDEX_LEAF, CM_KEY_INDEX_ROOT, CmpCompressedNameSize(), CmpCopyCompressedName(), CmpFindSubKeyInLeaf(), CmpFindSubKeyInRoot(), _CM_KEY_FAST_INDEX::Count, _CM_KEY_INDEX::Count, FALSE, _CM_KEY_NODE::Flags, _HHIVE::Free, HCELL_INDEX, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, HvGetCellType, HvIsCellAllocated(), KEY_COMP_NAME, _CM_KEY_FAST_INDEX::List, _CM_KEY_INDEX::List, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NULL, _CM_KEY_INDEX::Signature, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, and _CM_KEY_NODE::WorkVar.

Referenced by CmpFreeKeyByCell().

    01721                    :
    01722
    01723     Remove the subkey TargetKey refers to from ParentKey's list.
    01724
    01725     NOTE:   Assumes that caller has marked relevent cells dirty,
    01726             see CmpMarkIndexDirty.
    01727
    01728 Arguments:
    01729
    01730     Hive - pointer to hive control structure for hive of interest
    01731
    01732     ParentKey - key from whose subkey list delete is to be performed
    01733
    01734     TargetKey - key being deleted
    01735
    01736 Return Value:
    01737
    01738     TRUE - it worked, FALSE - it didn't, some resource problem
    01739
    01740 --*/
    01741 {
    01742     PCM_KEY_NODE    pcell;
    01743     HCELL_INDEX     LeafCell;
    01744     PCM_KEY_INDEX   Leaf;
    01745     PCM_KEY_FAST_INDEX FastIndex;
    01746     HCELL_INDEX     RootCell = HCELL_NIL;
    01747     PCM_KEY_INDEX   Root = NULL;
    01748     HCELL_INDEX     Child;
    01749     ULONG           Type;
    01750     ULONG           RootSelect;
    01751     ULONG           LeafSelect;
    01752     UNICODE_STRING  SearchName;
    01753     BOOLEAN         IsCompressed;
    01754     WCHAR           CompressedBuffer[50];
    01755
    01756     pcell = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
    01757     if (pcell->Flags & KEY_COMP_NAME) {
    01758         IsCompressed = TRUE;
    01759         SearchName.Length = CmpCompressedNameSize(pcell->Name, pcell->NameLength);
    01760         SearchName.MaximumLength = SearchName.Length;
    01761         if (SearchName.MaximumLength > sizeof(CompressedBuffer)) {
    01762             SearchName.Buffer = (Hive->Allocate)(SearchName.Length, FALSE);
    01763             if (SearchName.Buffer==NULL) {
    01764                 return(FALSE);
    01765             }
    01766         } else {
    01767             SearchName.Buffer = CompressedBuffer;
    01768         }
    01769         CmpCopyCompressedName(SearchName.Buffer,
    01770                               SearchName.MaximumLength,
    01771                               pcell->Name,
    01772                               pcell->NameLength);
    01773     } else {
    01774         IsCompressed = FALSE;
    01775         SearchName.Length = pcell->NameLength;
    01776         SearchName.MaximumLength = pcell->NameLength;
    01777         SearchName.Buffer = &(pcell->Name[0]);
    01778     }
    01779
    01780     pcell = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
    01781     Type = HvGetCellType(TargetKey);
    01782
    01783     ASSERT(pcell->SubKeyCounts[Type] != 0);
    01784     ASSERT(HvIsCellAllocated(Hive, pcell->SubKeyLists[Type]));
    01785
    01786     LeafCell = pcell->SubKeyLists[Type];
    01787     Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
    01788
    01789     if (Leaf->Signature == CM_KEY_INDEX_ROOT) {
    01790         RootSelect = CmpFindSubKeyInRoot(Hive, Leaf, &SearchName, &Child);
    01791
    01792         ASSERT(Child != FALSE);
    01793
    01794         Root = Leaf;
    01795         RootCell = LeafCell;
    01796         LeafCell = Child;
    01797         Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
    01798
    01799     }
    01800
    01801     ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
    01802            (Leaf->Signature == CM_KEY_FAST_LEAF));
    01803
    01804     LeafSelect = CmpFindSubKeyInLeaf(Hive, Leaf, pcell->WorkVar, &SearchName, &Child);
    01805
    01806     ASSERT(Child != HCELL_NIL);
    01807
    01808     //
    01809     // Leaf points to Index Leaf block
    01810     // Child is Index Leaf block cell
    01811     // LeafSelect is Index for List[]
    01812     //
    01813     pcell->SubKeyCounts[Type] -= 1;
    01814
    01815     Leaf->Count -= 1;
    01816     if (Leaf->Count == 0) {
    01817
    01818         //
    01819         // Empty Leaf, drop it.
    01820         //
    01821         HvFreeCell(Hive, LeafCell);
    01822
    01823         if (Root != NULL) {
    01824
    01825             Root->Count -= 1;
    01826             if (Root->Count == 0) {
    01827
    01828                 //
    01829                 // Root is empty, free it too.
    01830                 //
    01831                 HvFreeCell(Hive, RootCell);
    01832                 pcell->SubKeyLists[Type] = HCELL_NIL;
    01833
    01834             } else if (RootSelect < (ULONG)(Root->Count)) {
    01835
    01836                 //
    01837                 // Middle entry, squeeze root
    01838                 //
    01839                 RtlMoveMemory(
    01840                     (PVOID)&(Root->List[RootSelect]),
    01841                     (PVOID)&(Root->List[RootSelect+1]),
    01842                     (Root->Count - RootSelect) * sizeof(HCELL_INDEX)
    01843                     );
    01844             }
    01845             //
    01846             // Else RootSelect == last entry, so decrementing count
    01847             // was all we needed to do
    01848             //
    01849
    01850         } else {
    01851
    01852             pcell->SubKeyLists[Type] = HCELL_NIL;
    01853
    01854         }
    01855
    01856     } else if (LeafSelect < (ULONG)(Leaf->Count)) {
    01857
    01858         if (Leaf->Signature == CM_KEY_INDEX_LEAF) {
    01859             RtlMoveMemory((PVOID)&(Leaf->List[LeafSelect]),
    01860                           (PVOID)&(Leaf->List[LeafSelect+1]),
    01861                           (Leaf->Count - LeafSelect) * sizeof(HCELL_INDEX));
    01862         } else {
    01863             FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
    01864             RtlMoveMemory((PVOID)&(FastIndex->List[LeafSelect]),
    01865                           (PVOID)&(FastIndex->List[LeafSelect+1]),
    01866                           (FastIndex->Count - LeafSelect) * sizeof(CM_INDEX));
    01867         }
    01868     }
    01869     //
    01870     // Else LeafSelect == last entry, so decrementing count was enough
    01871     //
    01872
    01873     if ((IsCompressed) &&
    01874         (SearchName.MaximumLength > sizeof(CompressedBuffer))) {
    01875         (Hive->Free)(SearchName.Buffer, SearchName.Length);
    01876     }
    01877     return TRUE;
    01878 }
    }

VOID CmpReportNotify | ( | PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | PHHIVE | Hive,
|  | HCELL_INDEX | Cell,
|  | ULONG | NotifyMask
| ) |

Definition at line 191 of file cmnotify.c.

References Cell, CML_WORKER, CMLOG, CmpMasterHive, CmpReportNotifyHelper(), CMS_NOTIFY, Filter, _CM_KEY_NODE::Flags, _CMHIVE::Hive, Hive, HvGetCell, KEY_HIVE_ENTRY, KEY_HIVE_EXIT, PAGED_CODE, _CM_KEY_NODE::Parent, and _CM_KEY_CONTROL_BLOCK::ParentKcb.

    00199                    :
    00200
    00201     This routine is called when a notifiable event occurs. It will
    00202     apply CmpReportNotifyHelper to the hive the event occured in,
    00203     and the master hive if different.
    00204
    00205 Arguments:
    00206
    00207     KeyControlBlock - KCB of the key at which the event occured.
    00208             For create or delete this is the created or deleted key.
    00209
    00210     Hive - pointer to hive containing cell of Key at which event occured.
    00211
    00212     Cell - cell of Key at which event occured
    00213
    00214             (hive and cell correspond with name.)
    00215
    00216     Filter - event to be reported
    00217
    00218 Return Value:
    00219
    00220     NONE.
    00221
    00222 --*/
    00223 {
    00224     PCM_KEY_NODE pcell;
    00225     ULONG       flags;
    00226     ULONG       i;
    00227
    00228     PAGED_CODE();
    00229     CMLOG(CML_WORKER, CMS_NOTIFY) {
    00230         KdPrint(("CmpReportNotify:\n"));
    00231         KdPrint(("\tHive:%08lx Cell:%08lx Filter:%08lx\n", Hive, Cell, Filter));
    00232     }
    00233
    00234     pcell = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
    00235     //
    00236     // If the operation was create or delete, treat it as a change
    00237     // to the parent.
    00238     //
    00239     if (Filter == REG_NOTIFY_CHANGE_NAME) {
    00240         flags = pcell->Flags;
    00241         Cell = pcell->Parent;
    00242         if (flags & KEY_HIVE_ENTRY) {
    00243             Hive = &(CmpMasterHive->Hive);
    00244             pcell = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
    00245         }
    00246
    00247
    00248         KeyControlBlock = KeyControlBlock->ParentKcb;
    00249
    00250         //
    00251         // if we're at an exit/link node, back up the real node
    00252         // that MUST be it's parent.
    00253         //
    00254         if (pcell->Flags & KEY_HIVE_EXIT) {
    00255             Cell = pcell->Parent;
    00256         }
    00257         pcell = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
    00258     }
    00259
    00260     //
    00261     // Report to notifies waiting on the event's hive
    00262     //
    00263     CmpReportNotifyHelper(KeyControlBlock, Hive, Hive, pcell, Filter);
    00264
    00265
    00266     //
    00267     // If containing hive is not the master hive, apply to master hive
    00268     //
    00269     if (Hive != &(CmpMasterHive->Hive)) {
    00270         CmpReportNotifyHelper(KeyControlBlock,
    00271                               &(CmpMasterHive->Hive),
    00272                               Hive,
    00273                               pcell,
    00274                               Filter);
    00275     }
    00276
    00277     return;
    00278 }

BOOLEAN CmpResolveDriverDependencies | ( | IN PLIST_ENTRY | DriverListHead | ) |

Definition at line 920 of file cmboot.c.

References CmpOrderGroup(), _BOOT_DRIVER_NODE::Group, RtlEqualUnicodeString(), and TRUE.

Referenced by CmGetSystemDriverList().

    00926                    :
    00927
    00928     This routine orders driver nodes in a group based on their dependencies
    00929     on one another.  It removes any drivers that have circular dependencies
    00930     from the list.
    00931
    00932 Arguments:
    00933
    00934     DriverListHead - Supplies a pointer to the head of the list of
    00935             boot drivers to be sorted.
    00936
    00937 Return Value:
    00938
    00939     TRUE - Dependencies successfully resolved
    00940
    00941     FALSE - Corrupt hive.
    00942
    00943 --*/
    00944
    00945 {
    00946     PLIST_ENTRY CurrentEntry;
    00947     PBOOT_DRIVER_NODE GroupStart;
    00948     PBOOT_DRIVER_NODE GroupEnd;
    00949     PBOOT_DRIVER_NODE CurrentNode;
    00950
    00951     CurrentEntry = DriverListHead->Flink;
    00952
    00953     while (CurrentEntry != DriverListHead) {
    00954         //
    00955         // The list is already ordered by groups.  Find the first and
    00956         // last entry in each group, and order each of these sub-lists
    00957         // based on their dependencies.
    00958         //
    00959
    00960         GroupStart = CONTAINING_RECORD(CurrentEntry,
    00961                                        BOOT_DRIVER_NODE,
    00962                                        ListEntry.Link);
    00963         do {
    00964             GroupEnd = CONTAINING_RECORD(CurrentEntry,
    00965                                          BOOT_DRIVER_NODE,
    00966                                          ListEntry.Link);
    00967
    00968             CurrentEntry = CurrentEntry->Flink;
    00969             CurrentNode = CONTAINING_RECORD(CurrentEntry,
    00970                                             BOOT_DRIVER_NODE,
    00971                                             ListEntry.Link);
    00972
    00973             if (CurrentEntry == DriverListHead) {
    00974                 break;
    00975             }
    00976
    00977             if (!RtlEqualUnicodeString(&GroupStart->Group,
    00978                                        &CurrentNode->Group,
    00979                                        TRUE)) {
    00980                 break;
    00981             }
    00982
    00983         } while ( CurrentEntry != DriverListHead );
    00984
    00985         //
    00986         // GroupStart now points to the first driver node in the group,
    00987         // and GroupEnd points to the last driver node in the group.
    00988         //
    00989         CmpOrderGroup(GroupStart, GroupEnd);
    00990
    00991     }
    00992     return(TRUE);
    00993 }

NTSTATUS CmpSaveBootControlSet | ( | IN USHORT | ControlSetNum | ) |

ULONG CmpSearchForOpenSubKeys | ( | IN PCM_KEY_CONTROL_BLOCK | SearchKey,
|  | IN SUBKEY_SEARCH_TYPE | SearchType
| ) |

VOID CmpSearchKeyControlBlockTree | ( | PKCB_WORKER_ROUTINE | WorkerRoutine,
|  | PVOID | Context1,
|  | PVOID | Context2
| ) |

Definition at line 1071 of file cmsubs.c.

References ASSERT, ASSERT_KCB, CmpCacheTable, CmpCleanUpKcbCacheWithLock(), CmpHashTableSize, CmpRemoveFromDelayedClose(), Context1, Context2, _CM_KEY_CONTROL_BLOCK::Delete, KCB_WORKER_CONTINUE, KCB_WORKER_DELETE, KCB_WORKER_DONE, _CM_KEY_CONTROL_BLOCK::NextHash, and _CM_KEY_CONTROL_BLOCK::RefCount.

Referenced by CmpRefreshHive(), and CmUnloadKey().

    01078                    :
    01079
    01080     Traverse the kcb tree.  We will visit all nodes unless WorkerRoutine
    01081     tells us to stop part way through.
    01082
    01083     For each node, call WorkerRoutine(..., Context1, Contex2).  If it returns
    01084     KCB_WORKER_DONE, we are done, simply return.  If it returns
    01085     KCB_WORKER_CONTINUE, just continue the search. If it returns KCB_WORKER_DELETE,
    01086     the specified KCB is marked as deleted.
    01087
    01088     This routine has the side-effect of removing all delayed-close KCBs.
    01089
    01090 Arguments:
    01091
    01092     WorkerRoutine - applied to nodes witch Match.
    01093
    01094     Context1 - data we pass through
    01095
    01096     Context2 - data we pass through
    01097
    01098
    01099 Return Value:
    01100
    01101     NONE.
    01102
    01103 --*/
    01104 {
    01105     PCM_KEY_CONTROL_BLOCK   Current;
    01106     PCM_KEY_CONTROL_BLOCK   Next;
    01107     PCM_KEY_HASH *Prev;
    01108     ULONG                   WorkerResult;
    01109     ULONG                   i;
    01110
    01111     //
    01112     // Walk the hash table
    01113     //
    01114     for (i=0; i<CmpHashTableSize; i++) {
    01115         Prev = &CmpCacheTable[i];
    01116         while (*Prev) {
    01117             Current = CONTAINING_RECORD(*Prev,
    01118                                         CM_KEY_CONTROL_BLOCK,
    01119                                         KeyHash);
    01120             ASSERT_KCB(Current);
    01121             ASSERT(!Current->Delete);
    01122             if (Current->RefCount == 0) {
    01123                 //
    01124                 // This kcb is in DelayClose case, remove it.
    01125                 //
    01126                 CmpRemoveFromDelayedClose(Current);
    01127                 CmpCleanUpKcbCacheWithLock(Current);
    01128
    01129                 //
    01130                 // The HashTable is changed, start over in this index again.
    01131                 //
    01132                 Prev = &CmpCacheTable[i];
    01133                 continue;
    01134             }
    01135
    01136             WorkerResult = (WorkerRoutine)(Current, Context1, Context2);
    01137             if (WorkerResult == KCB_WORKER_DONE) {
    01138                 return;
    01139             } else if (WorkerResult == KCB_WORKER_DELETE) {
    01140                 ASSERT(Current->Delete);
    01141                 *Prev = Current->NextHash;
    01142                 continue;
    01143             } else {
    01144                 ASSERT(WorkerResult == KCB_WORKER_CONTINUE);
    01145                 Prev = &Current->NextHash;
    01146             }
    01147         }
    01148     }
    01149 }

NTSTATUS CmpSecurityMethod | ( | IN PVOID | Object,
|  | IN SECURITY_OPERATION_CODE | OperationCode,
|  | IN PSECURITY_INFORMATION | SecurityInformation,
|  | IN OUT PSECURITY_DESCRIPTOR | SecurityDescriptor,
|  | IN OUT PULONG | CapturedLength,
|  | IN OUT PSECURITY_DESCRIPTOR * | ObjectsSecurityDescriptor,
|  | IN POOL_TYPE | PoolType,
|  | IN PGENERIC_MAPPING | GenericMapping
| ) |

Definition at line 158 of file cmse.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, ASSERT_KEY_OBJECT, AssignSecurityDescriptor, CML_FLOW, CMLOG, CmpAssignSecurityDescriptor(), CmpLockRegistry(), CmpLockRegistryExclusive(), CmpQuerySecurityDescriptorInfo(), CmpReportNotify(), CmpSecurityExceptionFilter(), CmpSetSecurityDescriptorInfo(), CmpUnlockRegistry(), CMS_SEC, DeleteSecurityDescriptor, FALSE, kcb(), KeBugCheckEx(), Key, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObAssignObjectSecurityDescriptor(), PAGED_CODE, PagedPool, QuerySecurityDescriptor, SetSecurityDescriptor, and Status.

Referenced by CmpCreateObjectTypes(), and CmpDoCreateChild().

    00171                    :
    00172
    00173     This is the security method for registry objects.  It is responsible for
    00174     retrieving, setting, and deleting the security descriptor of a registry
    00175     object.  It is not used to assign the original security descriptor to an
    00176     object (use SeAssignSecurity for that purpose).
    00177
    00178
    00179     IT IS ASSUMED THAT THE OBJECT MANAGER HAS ALREADY DONE THE ACCESS
    00180     VALIDATIONS NECESSARY TO ALLOW THE REQUESTED OPERATIONS TO BE PERFORMED.
    00181
    00182 Arguments:
    00183
    00184     Object - Supplies a pointer to the object being used.
    00185
    00186     OperationCode - Indicates if the operation is for setting, querying, or
    00187         deleting the object's security descriptor.
    00188
    00189     SecurityInformation - Indicates which security information is being
    00190         queried or set.  This argument is ignored for the delete operation.
    00191
    00192     SecurityDescriptor - The meaning of this parameter depends on the
    00193         OperationCode:
    00194
    00195         QuerySecurityDescriptor - For the query operation this supplies the
    00196             buffer to copy the descriptor into.  The security descriptor is
    00197             assumed to have been probed up to the size passed in in Length.
    00198             Since it still points into user space, it must always be
    00199             accessed in a try clause in case it should suddenly disappear.
    00200
    00201         SetSecurityDescriptor - For a set operation this supplies the
    00202             security descriptor to copy into the object.  The security
    00203             descriptor must be captured before this routine is called.
    00204
    00205         DeleteSecurityDescriptor - It is ignored when deleting a security
    00206             descriptor.
    00207
    00208         AssignSecurityDescriptor - For assign operations this is the
    00209             security descriptor that will be assigned to the object.
    00210             It is assumed to be in kernel space, and is therefore not
    00211             probed or captured.
    00212
    00213     CapturedLength - For the query operation this specifies the length, in
    00214         bytes, of the security descriptor buffer, and upon return contains
    00215         the number of bytes needed to store the descriptor.  If the length
    00216         needed is greater than the length supplied the operation will fail.
    00217         It is ignored in the set and delete operation.
    00218
    00219         This parameter is assumed to be captured and probed as appropriate.
    00220
    00221     ObjectsSecurityDescriptor - For the Set operation this supplies the address
    00222         of a pointer to the object's current security descriptor.  This routine
    00223         will either modify the security descriptor in place or deallocate/
    00224         allocate a new security descriptor and use this variable to indicate
    00225         its new location.  For the query operation it simply supplies
    00226         the security descriptor being queried.
    00227
    00228     PoolType - For the set operation this specifies the pool type to use if
    00229         a new security descriptor needs to be allocated.  It is ignored
    00230         in the query and delete operation.
    00231
    00232     GenericMapping - Passed only for the set operation, this argument provides
    00233         the mapping of generic to specific/standard access types for the object
    00234         being accessed.  This mapping structure is expected to be safe to
    00235         access (i.e., captured if necessary) prior to be passed to this routine.
    00236
    00237 Return Value:
    00238
    00239     NTSTATUS - STATUS_SUCCESS if the operation is successful and an
    00240         appropriate error status otherwise.
    00241
    00242 --*/
    00243
    00244 {
    00245     PCM_KEY_CONTROL_BLOCK kcb;
    00246     NTSTATUS Status;
    00247     CM_KEY_REFERENCE Key;
    00248
    00249     //
    00250     //  Make sure the common parts of our input are proper
    00251     //
    00252
    00253     PAGED_CODE();
    00254     ASSERT_KEY_OBJECT(Object);
    00255
    00256     ASSERT( (OperationCode == SetSecurityDescriptor) ||
    00257             (OperationCode == QuerySecurityDescriptor) ||
    00258             (OperationCode == AssignSecurityDescriptor) ||
    00259             (OperationCode == DeleteSecurityDescriptor) );
    00260
    00261     //
    00262     // Lock hive for shared or exclusive, depending on what we need
    00263     // to do.
    00264     //
    00265     if (OperationCode == QuerySecurityDescriptor) {
    00266         CmpLockRegistry();
    00267     } else {
    00268         CmpLockRegistryExclusive();
    00269     }
    00270
    00271     if (((PCM_KEY_BODY)Object)->KeyControlBlock->Delete) {
    00272         //
    00273         // Key has been deleted, performing security operations on
    00274         // it is Not Allowed.
    00275         //
    00276         CmpUnlockRegistry();
    00277         return(STATUS_KEY_DELETED);
    00278     }
    00279
    00280     kcb = ((PCM_KEY_BODY)Object)->KeyControlBlock;
    00281
    00282     try {
    00283         //
    00284         //  This routine simply cases off of the operation code to decide
    00285         //  which support routine to call
    00286         //
    00287
    00288         switch (OperationCode) {
    00289
    00290         case SetSecurityDescriptor:
    00291
    00292             //
    00293             //  check the rest of our input and call the set security
    00294             //  method
    00295             //
    00296             ASSERT( (PoolType == PagedPool) || (PoolType == NonPagedPool) );
    00297
    00298             Status = CmpSetSecurityDescriptorInfo( kcb,
    00299                                                    SecurityInformation,
    00300                                                    SecurityDescriptor,
    00301                                                    ObjectsSecurityDescriptor,
    00302                                                    PoolType,
    00303                                                    GenericMapping );
    00304
    00305             //
    00306             // this is the one and only path on which a user could change
    00307             // a security descriptor, therefore, report such changes for
    00308             // notification here.
    00309             //
    00310             if (NT_SUCCESS(Status)) {
    00311                 CmpReportNotify(kcb,
    00312                                 kcb->KeyHive,
    00313                                 kcb->KeyCell,
    00314                                 REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_SECURITY);
    00315
    00316             }
    00317
    00318             break;
    00319
    00320         case QuerySecurityDescriptor:
    00321
    00322             //
    00323             //  check the rest of our input and call the default query security
    00324             //  method
    00325             //
    00326             ASSERT( CapturedLength != NULL );
    00327             Status = CmpQuerySecurityDescriptorInfo( kcb,
    00328                                                      SecurityInformation,
    00329                                                      SecurityDescriptor,
    00330                                                      CapturedLength,
    00331                                                      ObjectsSecurityDescriptor );
    00332             break;
    00333
    00334         case DeleteSecurityDescriptor:
    00335
    00336             //
    00337             // Nobody should ever call the delete method.  When the key is
    00338             // freed, the security descriptor associated with it is
    00339             // explicitly freed (CmpFreeSecurityDescriptor)
    00340             //
    00341             ASSERT(FALSE);
    00342
    00343             break;
    00344
    00345         case AssignSecurityDescriptor:
    00346
    00347             //
    00348             // Set the SecurityDescriptor field in the object's header to
    00349             // NULL.  This indicates that our security method needs to be
    00350             // called for any security descriptor operations.
    00351             //
    00352
    00353             Status = ObAssignObjectSecurityDescriptor(Object, NULL, PagedPool);
    00354
    00355             ASSERT( NT_SUCCESS( Status ));
    00356
    00357             //
    00358             // Assign the actual descriptor.
    00359             //
    00360             Status = CmpAssignSecurityDescriptor( kcb->KeyHive,
    00361                                                   kcb->KeyCell,
    00362                                                   kcb->KeyNode,
    00363                                                   SecurityDescriptor );
    00364             //
    00365             // Security has been changed, update the cache.
    00366             //
    00367             ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00368             kcb->Security = kcb->KeyNode->Security;
    00369
    00370             break;
    00371
    00372         default:
    00373
    00374             //
    00375             //  Bugcheck on any other operation code,  We won't get here if
    00376             //  the earlier asserts are still checked.
    00377             //
    00378             KeBugCheckEx( REGISTRY_ERROR,3,1,(ULONG_PTR)kcb,0);
    00379
    00380         }
    00381
    00382     } except (CmpSecurityExceptionFilter(GetExceptionInformation())) {
    00383         CMLOG(CML_FLOW, CMS_SEC) {
    00384             KdPrint(("!!CmpSecurityMethod: code:%08lx\n", GetExceptionCode()));
    00385         }
    00386         Status = GetExceptionCode();
    00387     }
    00388
    00389
    00390     CmpUnlockRegistry();
    00391     return(Status);
    00392
    00393 }

VOID CmpSetCurrentProfile | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ControlSet,
|  | IN PCM_HARDWARE_PROFILE | Profile
| ) |

Definition at line 1221 of file cmboot.c.

References CmpFindProfileOption(), CmpFindValueByName, CmpValueToData, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, L, Name, NULL, PCM_HARDWARE_PROFILE, RtlInitUnicodeString(), and _CM_KEY_VALUE::Type.

    01229                    :
    01230
    01231     Edits the in-memory copy of the registry to reflect the hardware
    01232     profile that the system is booting from.
    01233
    01234 Arguments:
    01235
    01236     Hive - Supplies a pointer to the hive control structure
    01237
    01238     ControlSet - Supplies the HCELL_INDEX of the current control set.
    01239
    01240     Profile - Supplies a pointer to the selected hardware profile
    01241
    01242 Return Value:
    01243
    01244     None.
    01245
    01246 --*/
    01247
    01248 {
    01249     HCELL_INDEX IDConfigDB;
    01250     PCM_KEY_NODE IDConfigNode;
    01251     HCELL_INDEX CurrentConfigCell;
    01252     PCM_KEY_VALUE CurrentConfigValue;
    01253     UNICODE_STRING Name;
    01254     PULONG CurrentConfig;
    01255     ULONG realsize;
    01256
    01257     IDConfigDB = CmpFindProfileOption(Hive,
    01258                                       ControlSet,
    01259                                       NULL,
    01260                                       NULL,
    01261                                       NULL);
    01262     if (IDConfigDB != HCELL_NIL) {
    01263         IDConfigNode = (PCM_KEY_NODE)HvGetCell(Hive, IDConfigDB);
    01264         RtlInitUnicodeString(&Name, L"CurrentConfig");
    01265         CurrentConfigCell = CmpFindValueByName(Hive,
    01266                                                IDConfigNode,
    01267                                                &Name);
    01268         if (CurrentConfigCell != HCELL_NIL) {
    01269             CurrentConfigValue = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentConfigCell);
    01270             if (CurrentConfigValue->Type == REG_DWORD) {
    01271                 CurrentConfig = (PULONG)CmpValueToData(Hive,
    01272                                                        CurrentConfigValue,
    01273                                                        realsize);
    01274                 *CurrentConfig = Profile->Id;
    01275             }
    01276         }
    01277     }
    01278
    01279
    01280 }

VOID CmpSetGlobalQuotaAllowed | ( | VOID |  | ) |

Definition at line 354 of file cmgquota.c.

References CmpGlobalQuota, and CmpGlobalQuotaAllowed.

Referenced by CmLoadKey(), CmpLoadHiveVolatile(), and CmRestoreKey().

    00359                    :
    00360
    00361     Enables registry quota
    00362
    00363     NOTE:   Do NOT put this in init segment, we call it after
    00364             that code has been freed!
    00365
    00366 Return Value:
    00367
    00368     NONE.
    00369
    00370 --*/
    00371 {
    00372      CmpGlobalQuotaAllowed = CmpGlobalQuota;
    00373 }
    }

VOID CmpSetVersionData | ( | VOID |  | ) |

Definition at line 1545 of file cmsysini.c.

References CmCSDVersionString, CmpConfigureProcessors(), CmpHiveRootSecurityDescriptor(), CmpInterlockedFunction(), CmpProcessorControl, CmVersionString, DbgPrint, ExFreePool(), FALSE, L, NT_SUCCESS, NtBuildNumber, NtClose(), NtCreateKey(), NtDeleteValueKey(), NtSetValueKey(), NTSTATUS(), NtSystemRoot, NULL, nullclass, ObjectAttributes, PAGED_CODE, RtlAnsiStringToUnicodeString(), RtlFreeStringRoutine, RtlInitAnsiString(), RtlInitUnicodeString(), sprintf(), and ValueBuffer.

Referenced by NtInitializeRegistry().

    01550                    :
    01551
    01552     Create \REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion:
    01553                 CurrentVersion = VER_PRODUCTVERSION_STR             // From ntverp.h
    01554                 CurrentBuildNumber = VER_PRODUCTBUILD               // From ntverp.h
    01555                 CurrentType = "[Multiprocessor|Uniprocessor]        // From NT_UP
    01556                                 [Retail|Free|Checked]"              // From DBG, DEVL
    01557                 SystemRoot = "[c:\nt]"
    01558
    01559
    01560     NOTE:   It is not worth bugchecking over this, so if it doesn't
    01561             work, just fail.
    01562
    01563 Arguments:
    01564
    01565 Return Value:
    01566
    01567 --*/
    01568 {
    01569     ANSI_STRING     AnsiString;
    01570     UNICODE_STRING  NameString;
    01571     UNICODE_STRING  ValueString;
    01572     HANDLE          key1, key2;
    01573     UCHAR           WorkString[128];
    01574     WCHAR           ValueBuffer[128];
    01575     OBJECT_ATTRIBUTES   ObjectAttributes;
    01576     NTSTATUS            status;
    01577     PUCHAR              proctype;
    01578     PUCHAR              buildtype;
    01579     PSECURITY_DESCRIPTOR SecurityDescriptor;
    01580
    01581     PAGED_CODE();
    01582     //
    01583     // Get default security descriptor for the nodes we will create.
    01584     //
    01585     SecurityDescriptor = CmpHiveRootSecurityDescriptor();
    01586
    01587     //
    01588     // Create the key
    01589     //
    01590     RtlInitUnicodeString(
    01591         &NameString,
    01592         L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft"
    01593         );
    01594
    01595     InitializeObjectAttributes(
    01596         &ObjectAttributes,
    01597         &NameString,
    01598         OBJ_CASE_INSENSITIVE,
    01599         (HANDLE)NULL,
    01600         SecurityDescriptor
    01601         );
    01602
    01603     status = NtCreateKey(
    01604                 &key1,
    01605                 KEY_CREATE_SUB_KEY,
    01606                 &ObjectAttributes,
    01607                 0,
    01608                 &nullclass,
    01609                 0,
    01610                 NULL
    01611                 );
    01612
    01613     if (!NT_SUCCESS(status)) {
    01614 #if DBG
    01615         DbgPrint("CMINIT: CreateKey of %wZ failed - Status == %lx\n",
    01616                  &NameString, status);
    01617 #endif
    01618         ExFreePool(SecurityDescriptor);
    01619         return;
    01620     }
    01621
    01622     RtlInitUnicodeString(
    01623         &NameString,
    01624         L"Windows NT"
    01625         );
    01626
    01627     InitializeObjectAttributes(
    01628         &ObjectAttributes,
    01629         &NameString,
    01630         OBJ_CASE_INSENSITIVE,
    01631         key1,
    01632         SecurityDescriptor
    01633         );
    01634
    01635     status = NtCreateKey(
    01636                 &key2,
    01637                 KEY_SET_VALUE,
    01638                 &ObjectAttributes,
    01639                 0,
    01640                 &nullclass,
    01641                 0,
    01642                 NULL
    01643                 );
    01644     NtClose(key1);
    01645     RtlInitUnicodeString(
    01646         &NameString,
    01647         L"CurrentVersion"
    01648         );
    01649
    01650     InitializeObjectAttributes(
    01651         &ObjectAttributes,
    01652         &NameString,
    01653         OBJ_CASE_INSENSITIVE,
    01654         key2,
    01655         SecurityDescriptor
    01656         );
    01657
    01658     status = NtCreateKey(
    01659                 &key1,
    01660                 KEY_SET_VALUE,
    01661                 &ObjectAttributes,
    01662                 0,
    01663                 &nullclass,
    01664                 0,
    01665                 NULL
    01666                 );
    01667     NtClose(key2);
    01668     ExFreePool(SecurityDescriptor);
    01669     if (!NT_SUCCESS(status)) {
    01670 #if DBG
    01671         DbgPrint("CMINIT: CreateKey of %wZ failed - Status == %lx\n",
    01672                  &NameString, status);
    01673 #endif
    01674         return;
    01675     }
    01676
    01677
    01678     //
    01679     // Set the value entries for the key
    01680     //
    01681     RtlInitUnicodeString(
    01682         &NameString,
    01683         L"CurrentVersion"
    01684         );
    01685
    01686     status = NtSetValueKey(
    01687         key1,
    01688         &NameString,
    01689         0,              // TitleIndex
    01690         REG_SZ,
    01691         CmVersionString.Buffer,
    01692         CmVersionString.Length + sizeof( UNICODE_NULL )
    01693         );
    01694 #if DBG
    01695     if (!NT_SUCCESS(status)) {
    01696         DbgPrint("CMINIT: SetValueKey of %wZ failed - Status == %lx\n",
    01697                  &NameString, status);
    01698     }
    01699 #endif
    01700     (RtlFreeStringRoutine)( CmVersionString.Buffer );
    01701     RtlInitUnicodeString( &CmVersionString, NULL );
    01702
    01703     RtlInitUnicodeString(
    01704         &NameString,
    01705         L"CurrentBuildNumber"
    01706         );
    01707
    01708     sprintf(
    01709         WorkString,
    01710         "%u",
    01711         NtBuildNumber & 0xFFFF
    01712         );
    01713     RtlInitAnsiString( &AnsiString, WorkString );
    01714
    01715     ValueString.Buffer = ValueBuffer;
    01716     ValueString.Length = 0;
    01717     ValueString.MaximumLength = sizeof( ValueBuffer );
    01718
    01719     RtlAnsiStringToUnicodeString( &ValueString, &AnsiString, FALSE );
    01720
    01721     status = NtSetValueKey(
    01722         key1,
    01723         &NameString,
    01724         0,              // TitleIndex
    01725         REG_SZ,
    01726         ValueString.Buffer,
    01727         ValueString.Length + sizeof( UNICODE_NULL )
    01728         );
    01729 #if DBG
    01730     if (!NT_SUCCESS(status)) {
    01731         DbgPrint("CMINIT: SetValueKey of %wZ failed - Status == %lx\n",
    01732                  &NameString, status);
    01733     }
    01734 #endif
    01735
    01736     RtlInitUnicodeString(
    01737         &NameString,
    01738         L"CurrentType"
    01739         );
    01740
    01741 #if defined(NT_UP)
    01742     proctype = "Uniprocessor";
    01743 #else
    01744     proctype = "Multiprocessor";
    01745 #endif
    01746
    01747 #if DBG
    01748     buildtype = "Checked";
    01749 #else
    01750 #if DEVL
    01751     buildtype = "Free";
    01752 #else
    01753     buildtype = "Retail";
    01754 #endif
    01755
    01756 #endif
    01757
    01758     sprintf(
    01759         WorkString,
    01760         "%s %s",
    01761         proctype,
    01762         buildtype
    01763         );
    01764     RtlInitAnsiString( &AnsiString, WorkString );
    01765
    01766     ValueString.Buffer = ValueBuffer;
    01767     ValueString.Length = 0;
    01768     ValueString.MaximumLength = sizeof( ValueBuffer );
    01769
    01770     RtlAnsiStringToUnicodeString( &ValueString, &AnsiString, FALSE );
    01771
    01772     status = NtSetValueKey(
    01773         key1,
    01774         &NameString,
    01775         0,              // TitleIndex
    01776         REG_SZ,
    01777         ValueString.Buffer,
    01778         ValueString.Length + sizeof( UNICODE_NULL )
    01779         );
    01780
    01781     RtlInitUnicodeString(
    01782         &NameString,
    01783         L"CSDVersion"
    01784         );
    01785
    01786     if (CmCSDVersionString.Length != 0) {
    01787         status = NtSetValueKey(
    01788             key1,
    01789             &NameString,
    01790             0,              // TitleIndex
    01791             REG_SZ,
    01792             CmCSDVersionString.Buffer,
    01793             CmCSDVersionString.Length + sizeof( UNICODE_NULL )
    01794             );
    01795 #if DBG
    01796         if (!NT_SUCCESS(status)) {
    01797             DbgPrint("CMINIT: SetValueKey of %wZ failed - Status == %lx\n",
    01798                      &NameString, status);
    01799         }
    01800 #endif
    01801         (RtlFreeStringRoutine)( CmCSDVersionString.Buffer );
    01802         RtlInitUnicodeString( &CmCSDVersionString, NULL );
    01803     } else {
    01804         status = NtDeleteValueKey(
    01805             key1,
    01806             &NameString
    01807             );
    01808 #if DBG
    01809         if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
    01810             DbgPrint("CMINIT: DeleteValueKey of %wZ failed - Status == %lx\n",
    01811                      &NameString, status);
    01812         }
    01813 #endif
    01814     }
    01815     RtlInitUnicodeString(&NameString,
    01816                          L"SystemRoot");
    01817     status = NtSetValueKey(key1,
    01818                            &NameString,
    01819                            0,
    01820                            REG_SZ,
    01821                            NtSystemRoot.Buffer,
    01822                            NtSystemRoot.Length + sizeof(UNICODE_NULL));
    01823 #if DBG
    01824     if (!NT_SUCCESS(status)) {
    01825         DbgPrint("CMINIT: SetValueKey of %wZ failed - Status == %lx\n",
    01826                  &NameString,
    01827                  status);
    01828     }
    01829 #endif
    01830     NtClose(key1);
    01831
    01832     //
    01833     // Set each processor to it's optimal configuration.
    01834     //
    01835     // Note: this call is performed interlocked such that the user
    01836     // can disable this automatic configuration update.
    01837     //
    01838
    01839     CmpInterlockedFunction(CmpProcessorControl, CmpConfigureProcessors);
    01840
    01841     return;
    01842 }

BOOLEAN CmpSortDriverList | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | ControlSet,
|  | IN PLIST_ENTRY | DriverListHead
| ) |

Definition at line 744 of file cmboot.c.

References CmpDoSort(), CmpFindSubKeyByName(), CmpFindValueByName, CmpValueToData, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, Index, L, Name, NTSTATUS(), PHCELL_INDEX, RtlInitUnicodeString(), Status, _CM_KEY_VALUE::Type, and USHORT.

Referenced by CmGetSystemDriverList().

    00752                    :
    00753
    00754     Sorts the list of boot drivers by their groups based on the group
    00755     ordering in <control_set>\CONTROL\SERVICE_GROUP_ORDER:list
    00756
    00757     Does NOT do dependency ordering.
    00758
    00759 Arguments:
    00760
    00761     Hive - Supplies the hive control structure for the SYSTEM hive.
    00762
    00763     ControlSet - Supplies the HCELL_INDEX of the root of the control set.
    00764
    00765     DriverListHead - Supplies a pointer to the head of the list of
    00766             boot drivers to be sorted.
    00767
    00768 Return Value:
    00769
    00770     TRUE - List successfully sorted
    00771
    00772     FALSE - List is inconsistent and could not be sorted.
    00773
    00774 --*/
    00775
    00776 {
    00777     HCELL_INDEX Controls;
    00778     HCELL_INDEX GroupOrder;
    00779     HCELL_INDEX ListCell;
    00780     UNICODE_STRING Name;
    00781     UNICODE_STRING DependList;
    00782     PHCELL_INDEX Index;
    00783     NTSTATUS Status;
    00784     PCM_KEY_VALUE ListNode;
    00785     ULONG realsize;
    00786
    00787     //
    00788     // Find "CONTROL" node.
    00789     //
    00790     RtlInitUnicodeString(&Name, L"Control");
    00791     Controls = CmpFindSubKeyByName(Hive,
    00792                                    (PCM_KEY_NODE)HvGetCell(Hive,ControlSet),
    00793                                    &Name);
    00794     if (Controls == HCELL_NIL) {
    00795         return(FALSE);
    00796     }
    00797
    00798     //
    00799     // Find "SERVICE_GROUP_ORDER" subkey
    00800     //
    00801     RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
    00802     GroupOrder = CmpFindSubKeyByName(Hive,
    00803                                      (PCM_KEY_NODE)HvGetCell(Hive,Controls),
    00804                                      &Name);
    00805     if (GroupOrder == HCELL_NIL) {
    00806         return(FALSE);
    00807     }
    00808
    00809     //
    00810     // Find "list" value
    00811     //
    00812     RtlInitUnicodeString(&Name, L"list");
    00813     ListCell = CmpFindValueByName(Hive,
    00814                                   (PCM_KEY_NODE)HvGetCell(Hive,GroupOrder),
    00815                                   &Name);
    00816     if (ListCell == HCELL_NIL) {
    00817         return(FALSE);
    00818     }
    00819     ListNode = (PCM_KEY_VALUE)HvGetCell(Hive, ListCell);
    00820     if (ListNode->Type != REG_MULTI_SZ) {
    00821         return(FALSE);
    00822     }
    00823
    00824     DependList.Buffer = (PWSTR)CmpValueToData(Hive,ListNode,realsize);
    00825     DependList.Length = DependList.MaximumLength = (USHORT)realsize - sizeof(WCHAR);
    00826
    00827     //
    00828     // Dependency list is now pointed to by DependList->Buffer.  We need
    00829     // to sort the driver entry list.
    00830     //
    00831
    00832     return (CmpDoSort(DriverListHead, &DependList));
    00833
    00834 }

VOID CmpUnlockRegistry | ( |  | ) |

Definition at line 116 of file cmsubs3.c.

Referenced by CmDeleteKey(), CmDeleteValueKey(), CmEnumerateKey(), CmEnumerateValueKey(), CmGetSystemDriverList(), CmInitSystem1(), CmLoadKey(), CmNotifyRunDown(), CmpCloneControlSet(), CmpCloneHwProfile(), CmpCloseKeyObject(), CmpDeleteKeyObject(), CmpFileSetSize(), CmpLazyFlushWorker(), CmpLoadHiveVolatile(), CmpQueryKeyName(), CmpRefreshHive(), CmpSaveBootControlSet(), CmpSaveKeyByFileCopy(), CmpSecurityMethod(), CmQueryKey(), CmQueryMultipleValueKey(), CmQueryValueKey(), CmReplaceKey(), CmRestoreKey(), CmSaveKey(), CmSaveMergedKeys(), CmSetLastWriteTimeKey(), CmSetValueKey(), CmShutdownSystem(), CmUnloadKey(), NtCreateKey(), NtFlushKey(), NtInitializeRegistry(), NtNotifyChangeMultipleKeys(), NtOpenKey(), NtQueryOpenSubKeys(), and NtUnloadKey().

    00120                    :
    00121
    00122     Unlock the registry.
    00123
    00124 --*/
    00125 {
    00126     ASSERT_CM_LOCK_OWNED();
    00127     ExReleaseResource(&CmpRegistryLock);
    00128     KeLeaveCriticalRegion();
    00129 }

BOOLEAN CmpValidateHiveSecurityDescriptors | ( | IN PHHIVE | Hive | ) |

Definition at line 34 of file cmchek2.c.

References _HHIVE::BaseBlock, _CM_KEY_SECURITY::Blink, CML_FLOW, CML_MAJOR, CML_MINOR, CMLOG, CmpDumpSecurityDescriptor, CMS_SEC, _CM_KEY_SECURITY::Descriptor, _CM_KEY_SECURITY::DescriptorLength, FALSE, _CM_KEY_SECURITY::Flink, HCELL_INDEX, Hive, HvGetCell, HvIsCellAllocated(), PCM_KEY_SECURITY, _CM_KEY_SECURITY::ReferenceCount, _HBASE_BLOCK::RootCell, _CM_KEY_NODE::Security, SetUsed, SeValidSecurityDescriptor(), and TRUE.

Referenced by CmCheckRegistry().

    00039                    :
    00040
    00041     Walks the list of security descriptors present in the hive and passes
    00042     each security descriptor to RtlValidSecurityDescriptor.
    00043
    00044     Only applies to descriptors in Stable store.  Those in Volatile store
    00045     cannot have come from disk and therefore do not need this treatment
    00046     anyway.
    00047
    00048 Arguments:
    00049
    00050     Hive - Supplies pointer to the hive control structure
    00051
    00052 Return Value:
    00053
    00054     TRUE  - All security descriptors are valid
    00055     FALSE - At least one security descriptor is invalid
    00056
    00057 --*/
    00058
    00059 {
    00060     PCM_KEY_NODE RootNode;
    00061     PCM_KEY_SECURITY SecurityCell;
    00062     HCELL_INDEX ListAnchor;
    00063     HCELL_INDEX NextCell;
    00064     HCELL_INDEX LastCell;
    00065
    00066     CMLOG(CML_FLOW, CMS_SEC) {
    00067         KdPrint(("CmpValidateHiveSecurityDescriptor: Hive = %lx\n",(ULONG_PTR)Hive));
    00068     }
    00069     if (!HvIsCellAllocated(Hive,Hive->BaseBlock->RootCell)) {
    00070         //
    00071         // root cell HCELL_INDEX is bogus
    00072         //
    00073         return(FALSE);
    00074     }
    00075     RootNode = (PCM_KEY_NODE) HvGetCell(Hive, Hive->BaseBlock->RootCell);
    00076     ListAnchor = NextCell = RootNode->Security;
    00077
    00078     do {
    00079         if (!HvIsCellAllocated(Hive, NextCell)) {
    00080             CMLOG(CML_MAJOR, CMS_SEC) {
    00081                 KdPrint(("CM: CmpValidateHiveSecurityDescriptors\n"));
    00082                 KdPrint(("    NextCell: %08lx is invalid HCELL_INDEX\n",NextCell));
    00083             }
    00084             return(FALSE);
    00085         }
    00086         SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, NextCell);
    00087         if (NextCell != ListAnchor) {
    00088             //
    00089             // Check to make sure that our Blink points to where we just
    00090             // came from.
    00091             //
    00092             if (SecurityCell->Blink != LastCell) {
    00093                 CMLOG(CML_MAJOR, CMS_SEC) {
    00094                     KdPrint(("  Invalid Blink (%ld) on security cell %ld\n",SecurityCell->Blink, NextCell));
    00095                     KdPrint(("  should point to %ld\n", LastCell));
    00096                 }
    00097                 return(FALSE);
    00098             }
    00099         }
    00100         CMLOG(CML_MINOR, CMS_SEC) {
    00101             KdPrint(("CmpValidSD:  SD shared by %d nodes\n",SecurityCell->ReferenceCount));
    00102         }
    00103         if (!SeValidSecurityDescriptor(SecurityCell->DescriptorLength, &SecurityCell->Descriptor)) {
    00104             CMLOG(CML_MAJOR, CMS_SEC) {
    00105                 CmpDumpSecurityDescriptor(&SecurityCell->Descriptor,"INVALID DESCRIPTOR");
    00106             }
    00107             return(FALSE);
    00108         }
    00109         SetUsed(Hive, NextCell);
    00110         LastCell = NextCell;
    00111         NextCell = SecurityCell->Flink;
    00112     } while ( NextCell != ListAnchor );
    00113     return(TRUE);
    00114 }
    }

VOID CmpWorker | ( | IN OUT PREGISTRY_COMMAND | Command | ) |

NTSTATUS CmQueryKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN KEY_INFORMATION_CLASS | KeyInformationClass,
|  | IN PVOID | KeyInformation,
|  | IN ULONG | Length,
|  | IN PULONG | ResultLength
| ) |

Definition at line 647 of file cmapi.c.

References CML_WORKER, CMLOG, CmpConstructName(), CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpQueryKeyData(), CmpUnlockRegistry(), CMS_CM, ExFreePoolWithTag, _KEY_INFORMATION::KeyNameInformation, Name, NTSTATUS(), NULL, PKEY_INFORMATION, PROTECTED_POOL, and USHORT.

Referenced by EhQueryKey(), and NtQueryKey().

    00656                    :
    00657
    00658     Data about the class of a key, and the numbers and sizes of its
    00659     children and value entries may be queried with CmQueryKey.
    00660
    00661     NOTE: The returned lengths are guaranteed to be at least as
    00662           long as the described values, but may be longer in
    00663           some circumstances.
    00664
    00665 Arguments:
    00666
    00667     KeyControlBlock - pointer to the KCB that describes the key
    00668
    00669     KeyInformationClass - Specifies the type of information
    00670         returned in Buffer.  One of the following types:
    00671
    00672         KeyBasicInformation - return last write time, title index, and name.
    00673             (See KEY_BASIC_INFORMATION)
    00674
    00675         KeyNodeInformation - return last write time, title index, name, class.
    00676             (See KEY_NODE_INFORMATION)
    00677
    00678         KeyFullInformation - return all data except for name and security.
    00679             (See KEY_FULL_INFORMATION)
    00680
    00681     KeyInformation -Supplies pointer to buffer to receive the data.
    00682
    00683     Length - Length of KeyInformation in bytes.
    00684
    00685     ResultLength - Number of bytes actually written into KeyInformation.
    00686
    00687 Return Value:
    00688
    00689     NTSTATUS - Result code from call, among the following:
    00690
    00691         <TBS>
    00692
    00693 --*/
    00694 {
    00695     NTSTATUS    status;
    00696
    00697     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmQueryKey\n"));
    00698
    00699
    00700
    00701     CmpLockRegistry();
    00702
    00703     // Mark the hive as read only
    00704     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00705
    00706     try {
    00707
    00708         //
    00709         // request for the FULL path of the key
    00710         //
    00711         if( KeyInformationClass == KeyNameInformation ) {
    00712             if (KeyControlBlock->Delete ) {
    00713                 //
    00714                 // special case: return key deleted status, but still fill the full name of the key.
    00715                 //
    00716                 status = STATUS_KEY_DELETED;
    00717             } else {
    00718                 status = STATUS_SUCCESS;
    00719             }
    00720
    00721             if( KeyControlBlock->NameBlock ) {
    00722
    00723                 PUNICODE_STRING Name;
    00724                 Name = CmpConstructName(KeyControlBlock);
    00725                 if (Name == NULL) {
    00726                     status = STATUS_INSUFFICIENT_RESOURCES;
    00727                 } else {
    00728                     ULONG       requiredlength;
    00729                     ULONG       minimumlength;
    00730                     USHORT      NameLength;
    00731                     LONG        leftlength;
    00732                     PKEY_INFORMATION pbuffer = (PKEY_INFORMATION)KeyInformation;
    00733
    00734                     NameLength = Name->Length;
    00735
    00736                     requiredlength = FIELD_OFFSET(KEY_NAME_INFORMATION, Name) + NameLength;
    00737
    00738                     minimumlength = FIELD_OFFSET(KEY_NAME_INFORMATION, Name);
    00739
    00740                     *ResultLength = requiredlength;
    00741                     if (Length < minimumlength) {
    00742
    00743                         status = STATUS_BUFFER_TOO_SMALL;
    00744
    00745                     } else {
    00746                         //
    00747                         // Fill in the length of the name
    00748                         //
    00749                         pbuffer->KeyNameInformation.NameLength = NameLength;
    00750
    00751                         //
    00752                         // Now copy the full name into the user buffer, if enough space
    00753                         //
    00754                         leftlength = Length - minimumlength;
    00755                         requiredlength = NameLength;
    00756                         if (leftlength < (LONG)requiredlength) {
    00757                             requiredlength = leftlength;
    00758                             status = STATUS_BUFFER_OVERFLOW;
    00759                         }
    00760
    00761                         //
    00762                         // If not enough space, copy how much we can and return overflow
    00763                         //
    00764                         RtlCopyMemory(
    00765                             &(pbuffer->KeyNameInformation.Name[0]),
    00766                             Name->Buffer,
    00767                             requiredlength
    00768                             );
    00769                     }
    00770
    00771                     ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
    00772                 }
    00773             }
    00774         } else if(KeyControlBlock->Delete ) {
    00775             //
    00776             // key already deleted
    00777             //
    00778             status = STATUS_KEY_DELETED;
    00779         } else {
    00780             //
    00781             // call a worker to perform data transfer
    00782             //
    00783
    00784             status = CmpQueryKeyData(KeyControlBlock->KeyHive,
    00785                                      KeyControlBlock->KeyNode,
    00786                                      KeyInformationClass,
    00787                                      KeyInformation,
    00788                                      Length,
    00789                                      ResultLength);
    00790         }
    00791
    00792     } finally {
    00793         CmpUnlockRegistry();
    00794     }
    00795
    00796     // Mark the hive as read only
    00797     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00798
    00799     return status;
    00800 }

NTSTATUS CmQueryMultipleValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PKEY_VALUE_ENTRY | ValueEntries,
|  | IN ULONG | EntryCount,
|  | IN PVOID | ValueBuffer,
|  | IN OUT PULONG | BufferLength,
|  | IN OPTIONAL PULONG | ResultLength
| ) |

Definition at line 940 of file cmapi.c.

References CML_WORKER, CMLOG, CmpFindValueByName, CmpIsHKeyValueSmall, CmpLockRegistry(), CmpMarkAllBinsReadOnly, CmpUnlockRegistry(), CMS_CM, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), PAGED_CODE, ProbeAndReadUnicodeString, ProbeForRead, Status, TRUE, _CM_KEY_VALUE::Type, UserMode, ValueBuffer, and ValueName.

Referenced by NtQueryMultipleValueKey().

    00950                    :
    00951
    00952     Multiple values of any key may be queried atomically with
    00953     this api.
    00954
    00955 Arguments:
    00956
    00957     KeyControlBlock - Supplies the key to be queried.
    00958
    00959     ValueEntries - Returns an array of KEY_VALUE_ENTRY structures, one for each value.
    00960
    00961     EntryCount - Supplies the number of entries in the ValueNames and ValueEntries arrays
    00962
    00963     ValueBuffer - Returns the value data for each value.
    00964
    00965     BufferLength - Supplies the length of the ValueBuffer array in bytes.
    00966                    Returns the length of the ValueBuffer array that was filled in.
    00967
    00968     ResultLength - if present, Returns the length in bytes of the ValueBuffer
    00969                     array required to return the requested values of this key.
    00970
    00971 Return Value:
    00972
    00973     NTSTATUS
    00974
    00975 --*/
    00976
    00977 {
    00978     PHHIVE Hive;
    00979     NTSTATUS Status;
    00980     ULONG i;
    00981     UNICODE_STRING CurrentName;
    00982     HCELL_INDEX ValueCell;
    00983     PCM_KEY_VALUE ValueNode;
    00984     ULONG RequiredLength = 0;
    00985     ULONG UsedLength = 0;
    00986     ULONG DataLength;
    00987     BOOLEAN BufferFull = FALSE;
    00988     BOOLEAN Small;
    00989     PUCHAR Data;
    00990     KPROCESSOR_MODE PreviousMode;
    00991
    00992     PAGED_CODE();
    00993     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmQueryMultipleValueKey\n"));
    00994
    00995
    00996     CmpLockRegistry();
    00997     if (KeyControlBlock->Delete) {
    00998         CmpUnlockRegistry();
    00999         return STATUS_KEY_DELETED;
    01000     }
    01001     Hive = KeyControlBlock->KeyHive;
    01002     Status = STATUS_SUCCESS;
    01003
    01004     // Mark the hive as read only
    01005     CmpMarkAllBinsReadOnly(Hive);
    01006
    01007     PreviousMode = KeGetPreviousMode();
    01008     try {
    01009         for (i=0; i < EntryCount; i++) {
    01010             //
    01011             // find the data
    01012             //
    01013             if (PreviousMode == UserMode) {
    01014                 CurrentName = ProbeAndReadUnicodeString(ValueEntries[i].ValueName);
    01015                 ProbeForRead(CurrentName.Buffer,CurrentName.Length,sizeof(WCHAR));
    01016             } else {
    01017                 CurrentName = *(ValueEntries[i].ValueName);
    01018             }
    01019             ValueCell = CmpFindValueByName(Hive,
    01020                                            KeyControlBlock->KeyNode,
    01021                                            &CurrentName);
    01022             if (ValueCell != HCELL_NIL) {
    01023
    01024                 ValueNode = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
    01025                 Small = CmpIsHKeyValueSmall(DataLength, ValueNode->DataLength);
    01026
    01027                 //
    01028                 // Round up UsedLength and RequiredLength to a ULONG boundary
    01029                 //
    01030                 UsedLength = (UsedLength + sizeof(ULONG)-1) & ~(sizeof(ULONG)-1);
    01031                 RequiredLength = (RequiredLength + sizeof(ULONG)-1) & ~(sizeof(ULONG)-1);
    01032
    01033                 //
    01034                 // If there is enough room for this data value in the buffer,
    01035                 // fill it in now. Otherwise, mark the buffer as full. We must
    01036                 // keep iterating through the values in order to determine the
    01037                 // RequiredLength.
    01038                 //
    01039                 if ((UsedLength + DataLength <= *BufferLength) &&
    01040                     (!BufferFull)) {
    01041                     if (DataLength > 0) {
    01042                         if (Small) {
    01043                             Data = (PUCHAR)&ValueNode->Data;
    01044                         } else {
    01045                             Data = (PUCHAR)HvGetCell(Hive, ValueNode->Data);
    01046                         }
    01047                         RtlCopyMemory((PUCHAR)ValueBuffer + UsedLength,
    01048                                       Data,
    01049                                       DataLength);
    01050                     }
    01051                     ValueEntries[i].Type = ValueNode->Type;
    01052                     ValueEntries[i].DataLength = DataLength;
    01053                     ValueEntries[i].DataOffset = UsedLength;
    01054                     UsedLength += DataLength;
    01055                 } else {
    01056                     BufferFull = TRUE;
    01057                     Status = STATUS_BUFFER_OVERFLOW;
    01058                 }
    01059                 RequiredLength += DataLength;
    01060
    01061             } else {
    01062                 Status = STATUS_OBJECT_NAME_NOT_FOUND;
    01063                 break;
    01064             }
    01065         }
    01066
    01067         if (NT_SUCCESS(Status) ||
    01068             (Status == STATUS_BUFFER_OVERFLOW)) {
    01069             *BufferLength = UsedLength;
    01070             if (ARGUMENT_PRESENT(ResultLength)) {
    01071                 *ResultLength = RequiredLength;
    01072             }
    01073         }
    01074
    01075     } finally {
    01076         CmpUnlockRegistry();
    01077     }
    01078
    01079     // Mark the hive as read only
    01080     CmpMarkAllBinsReadOnly(Hive);
    01081
    01082     return Status;
    01083 }

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

Definition at line 804 of file cmapi.c.

References Cell, CM_KCB_SYM_LINK_FOUND, CML_WORKER, CMLOG, CMP_GET_CACHED_ADDRESS, CmpDereferenceKeyControlBlockWithLock(), CmpFindValueByNameFromCache(), CmpLockRegistry(), CmpMakeValueCacheReadOnly, CmpMakeValueCacheReadWrite, CmpMarkAllBinsReadOnly, CmpQueryKeyValueData(), CmpUnlockRegistry(), CMS_CM, HCELL_INDEX, Index, LOCK_KCB_TREE, NTSTATUS(), PAGED_CODE, PHCELL_INDEX, UNLOCK_KCB_TREE, and ValueName.

Referenced by EhQueryValueKey(), and NtQueryValueKey().

    00814                    :
    00815
    00816     The ValueName, TitleIndex, Type, and Data for any one of a key's
    00817     value entries may be queried with CmQueryValueKey.
    00818
    00819     If KeyValueInformation is not long enough to hold all requested data,
    00820     STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    00821     set to the number of bytes actually required.
    00822
    00823 Arguments:
    00824
    00825     KeyControlBlock - pointer to the KCB that describes the key
    00826
    00827     ValueName  - The name of the value entry to return data for.
    00828
    00829     KeyValueInformationClass - Specifies the type of information
    00830         returned in KeyValueInformation.  One of the following types:
    00831
    00832         KeyValueBasicInformation - return time of last write, title
    00833             index, and name.  (See KEY_VALUE_BASIC_INFORMATION)
    00834
    00835         KeyValueFullInformation - return time of last write, title
    00836             index, name, class.  (See KEY_VALUE_FULL_INFORMATION)
    00837
    00838     KeyValueInformation -Supplies pointer to buffer to receive the data.
    00839
    00840     Length - Length of KeyValueInformation in bytes.
    00841
    00842     ResultLength - Number of bytes actually written into KeyValueInformation.
    00843
    00844 Return Value:
    00845
    00846     NTSTATUS - Result code from call, among the following:
    00847
    00848         <TBS>
    00849
    00850 --*/
    00851 {
    00852     NTSTATUS    status;
    00853     HCELL_INDEX childcell;
    00854     PHCELL_INDEX  childindex;
    00855     HCELL_INDEX Cell;
    00856     PCM_KEY_VALUE ValueData;
    00857     ULONG       Index;
    00858     BOOLEAN     ValueCached;
    00859     PPCM_CACHED_VALUE ContainingList;
    00860
    00861     PAGED_CODE();
    00862     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmQueryValueKey\n"));
    00863
    00864
    00865     CmpLockRegistry();
    00866
    00867     if (KeyControlBlock->Delete) {
    00868         CmpUnlockRegistry();
    00869         return STATUS_KEY_DELETED;
    00870     }
    00871
    00872     // Mark the hive as read only
    00873     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00874
    00875     LOCK_KCB_TREE();
    00876
    00877     if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) {
    00878         //
    00879         // The value list is now set to the KCB for symbolic link,
    00880         // Clean it up and set the value right before we do the query.
    00881         //
    00882         CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb);
    00883         KeyControlBlock->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    00884
    00885         KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
    00886         KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) KeyControlBlock->KeyNode->ValueList.List;
    00887     }
    00888
    00889
    00890     try {
    00891         //
    00892         // Find the data
    00893         //
    00894
    00895         ValueData = CmpFindValueByNameFromCache(KeyControlBlock->KeyHive,
    00896                                                 &(KeyControlBlock->ValueCache),
    00897                                                 &ValueName,
    00898                                                 &ContainingList,
    00899                                                 &Index,
    00900                                                 &ValueCached
    00901                                                 );
    00902         if (ValueData) {
    00903
    00904             // Trying to catch the BAD guy who writes over our pool.
    00905             CmpMakeValueCacheReadWrite(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00906
    00907             //
    00908             // call a worker to perform data transfer
    00909             //
    00910
    00911             status = CmpQueryKeyValueData(KeyControlBlock->KeyHive,
    00912                                           ContainingList,
    00913                                           ValueData,
    00914                                           ValueCached,
    00915                                           KeyValueInformationClass,
    00916                                           KeyValueInformation,
    00917                                           Length,
    00918                                           ResultLength);
    00919
    00920             // Trying to catch the BAD guy who writes over our pool.
    00921             CmpMakeValueCacheReadOnly(ValueCached,CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList));
    00922
    00923         } else {
    00924             status = STATUS_OBJECT_NAME_NOT_FOUND;
    00925         }
    00926
    00927     } finally {
    00928         UNLOCK_KCB_TREE();
    00929         CmpUnlockRegistry();
    00930     }
    00931
    00932     // Mark the hive as read only
    00933     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    00934
    00935     return status;
    00936 }

NTSTATUS CmRenameValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN UNICODE_STRING | SourceValueName,
|  | IN UNICODE_STRING | TargetValueName,
|  | IN ULONG | TargetIndex
| ) |

NTSTATUS CmReplaceKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PUNICODE_STRING | NewHiveName,
|  | IN PUNICODE_STRING | OldFileName
| ) |

Definition at line 2293 of file cmapi.c.

References _REGISTRY_COMMAND::Allocate, ASSERT, CHAR, CM_WRAP_LIMIT, _REGISTRY_COMMAND::CmHive, CML_BUGCHECK, CMLOG, CmpFree(), CmpGlobalQuotaAllowed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpUnlockRegistry(), CmpWorker(), CMS_SAVRES, _REGISTRY_COMMAND::Command, ErrorExit(), ExFreePool(), FALSE, _REGISTRY_COMMAND::FileAttributes, Hive, HIVE_HAS_BEEN_REPLACED, _HHIVE::HiveFlags, _CMHIVE::HiveList, HvFreeHive(), _REGISTRY_COMMAND::ImpersonationContext, _REGISTRY_COMMAND::NameInfoLength, _REGISTRY_COMMAND::NewName, NT_SUCCESS, NTSTATUS(), NULL, _REGISTRY_COMMAND::OldName, REG_CMD_HIVE_CLOSE, REG_CMD_HIVE_OPEN, REG_CMD_RENAME_HIVE, _REGISTRY_COMMAND::RegistryLockAquired, _REGISTRY_COMMAND::Status, Status, and TRUE.

Referenced by NtReplaceKey().

    02302                    :
    02303
    02304     Renames the hive file for a running system and replaces it with a new
    02305     file.  The new file is not actually used until the next boot.
    02306
    02307 Arguments:
    02308
    02309     Hive - Supplies a hive control structure for the hive to be replaced.
    02310
    02311     Cell - Supplies the HCELL_INDEX of the root cell of the hive to be
    02312            replaced.
    02313
    02314     NewHiveName - Supplies the name of the file which is to be installed
    02315             as the new hive.
    02316
    02317     OldFileName - Supplies the name of the file which the existing hive
    02318             file is to be renamed to.
    02319
    02320 Return Value:
    02321
    02322     NTSTATUS
    02323
    02324 --*/
    02325
    02326 {
    02327     REGISTRY_COMMAND Command;
    02328     CHAR ObjectInfoBuffer[512];
    02329     NTSTATUS Status;
    02330     OBJECT_ATTRIBUTES Attributes;
    02331     PCMHIVE NewHive;
    02332     POBJECT_NAME_INFORMATION NameInfo;
    02333     ULONG OldQuotaAllowed;
    02334     ULONG OldQuotaWarning;
    02335
    02336     CmpLockRegistryExclusive();
    02337
    02338     if (Hive->HiveFlags & HIVE_HAS_BEEN_REPLACED) {
    02339         CmpUnlockRegistry();
    02340         return STATUS_FILE_RENAMED;
    02341     }
    02342
    02343     //
    02344     // temporarily disable registry quota as we will be giving this memory back immediately!
    02345     //
    02346     OldQuotaAllowed = CmpGlobalQuotaAllowed;
    02347     OldQuotaWarning = CmpGlobalQuotaWarning;
    02348     CmpGlobalQuotaAllowed = CM_WRAP_LIMIT;
    02349     CmpGlobalQuotaWarning = CM_WRAP_LIMIT;
    02350
    02351     //
    02352     // First open the new hive file and check to make sure it is valid.
    02353     //
    02354     InitializeObjectAttributes(&Attributes,
    02355                                NewHiveName,
    02356                                OBJ_CASE_INSENSITIVE,
    02357                                NULL,
    02358                                NULL);
    02359
    02360     Command.RegistryLockAquired = TRUE;
    02361     Command.Command = REG_CMD_HIVE_OPEN;
    02362     Command.FileAttributes = &Attributes;
    02363     Command.Allocate = FALSE;
    02364     Command.ImpersonationContext = NULL;
    02365     CmpWorker(&Command);
    02366     Status = Command.Status;
    02367     if (!NT_SUCCESS(Status)) {
    02368         goto ErrorExit;
    02369     }
    02370     ASSERT(Command.Allocate == FALSE);
    02371
    02372     NewHive = Command.CmHive;
    02373
    02374     //
    02375     // The new hive exists, and is consistent, and we have it open.
    02376     // Now rename the current hive file.
    02377     //
    02378     Command.Command = REG_CMD_RENAME_HIVE;
    02379     Command.NewName = OldFileName;
    02380     Command.OldName = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer;
    02381     Command.NameInfoLength = sizeof(ObjectInfoBuffer);
    02382     Command.CmHive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    02383     CmpWorker(&Command);
    02384     Status = Command.Status;
    02385     if (!NT_SUCCESS(Status)) {
    02386             //
    02387         // rename failed, close the files associated with the new hive
    02388         //
    02389         Command.CmHive = NewHive;
    02390         Command.Command = REG_CMD_HIVE_CLOSE;
    02391         CmpWorker(&Command);
    02392         goto ErrorExit;
    02393     }
    02394
    02395     //
    02396     // The existing hive was successfully renamed, so try to rename the
    02397     // new file to what the old hive file was named.  (which was returned
    02398     // into ObjectInfoBuffer by the worker thread)
    02399     //
    02400     Hive->HiveFlags |= HIVE_HAS_BEEN_REPLACED;
    02401     NameInfo = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer;
    02402     Command.Command = REG_CMD_RENAME_HIVE;
    02403     Command.NewName = &NameInfo->Name;
    02404     Command.OldName = NULL;
    02405     Command.NameInfoLength = 0;
    02406     Command.CmHive = NewHive;
    02407     CmpWorker(&Command);
    02408     Status = Command.Status;
    02409     if (!NT_SUCCESS(Status)) {
    02410
    02411         //
    02412         // Close the handles to the new hive
    02413         //
    02414         Command.Command = REG_CMD_HIVE_CLOSE;
    02415         Command.CmHive = NewHive;
    02416         CmpWorker(&Command);
    02417
    02418         //
    02419         // We are in trouble now.  We have renamed the existing hive file,
    02420         // but we couldn't rename the new hive file!  Try to rename the
    02421         // existing hive file back to where it was.
    02422         //
    02423         Command.Command = REG_CMD_RENAME_HIVE;
    02424         Command.NewName = &NameInfo->Name;
    02425         Command.OldName = NULL;
    02426         Command.NameInfoLength = 0;
    02427         Command.CmHive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    02428         CmpWorker(&Command);
    02429         if (!NT_SUCCESS(Command.Status)) {
    02430             CMLOG(CML_BUGCHECK, CMS_SAVRES) {
    02431                 KdPrint(("CmReplaceKey: renamed existing hive file, but couldn't\n"));
    02432                 KdPrint(("              rename new hive file (%08lx) ",Status));
    02433                 KdPrint((" or replace old hive file (%08lx)!\n",Command.Status));
    02434             }
    02435
    02436             //
    02437             // WARNNOTE:
    02438             //      To get into this state, the user must have relevent
    02439             //      privileges, deliberately screw with system in an attempt
    02440             //      to defeat it, AND get it done in a narrow timing window.
    02441             //
    02442             //      Further, if it's a user profile, the system will
    02443             //      still come up.
    02444             //
    02445             //      Therefore, return an error code and go on.
    02446             //
    02447
    02448             Status = STATUS_REGISTRY_CORRUPT;
    02449
    02450         }
    02451     }
    02452
    02453     //
    02454     // All of the renaming is done.  However, we are holding an in-memory
    02455     // image of the new hive.  Release it, since it will not actually
    02456     // be used until next boot.
    02457     //
    02458     // Do not close the open file handles to the new hive, we need to
    02459     // keep it locked exclusively until the system is rebooted to prevent
    02460     // people from mucking with it.
    02461     //
    02462     RemoveEntryList(&(NewHive->HiveList));
    02463
    02464     HvFreeHive((PHHIVE)NewHive);
    02465
    02466     ASSERT( NewHive->HiveLock );
    02467     ExFreePool(NewHive->HiveLock);
    02468     CmpFree(NewHive, sizeof(CMHIVE));
    02469
    02470 ErrorExit:
    02471     //
    02472     // Set global quota back to what it was.
    02473     //
    02474     CmpGlobalQuotaAllowed = OldQuotaAllowed;
    02475     CmpGlobalQuotaWarning = OldQuotaWarning;
    02476
    02477     CmpUnlockRegistry();
    02478     return(Status);
    02479 }

NTSTATUS CmRestoreKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN HANDLE | FileHandle,
|  | IN ULONG | Flags
| ) |

Definition at line 97 of file cmsavres.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, _HHIVE::BaseBlock, Cell, _CM_INDEX::Cell, _CM_KEY_NODE::ChildHiveReference, CM_KCB_SUBKEY_HINT, CM_KEY_FAST_LEAF, CM_KEY_INDEX_ROOT, CML_MAJOR, CMLOG, CmpCleanUpKcbValueCache(), CmpCopyKeyPartial(), CmpCopyTree, CmpDeleteTree(), CmpDestroyTemporaryHive(), CmpFreeKeyByCell(), CmpInitializeHive(), CmpLoadHiveVolatile(), CmpLockRegistryExclusive(), CmpMasterHive, CmpProfileLoaded, CmpRefreshHive(), CmpReportNotify(), CmpSearchForOpenSubKeys(), CmpSetGlobalQuotaAllowed(), CmpUnlockRegistry(), CMS_SAVRES, _CM_KEY_INDEX::Count, _CM_KEY_FAST_INDEX::Count, DCmCheckRegistry, ExFreePoolWithTag, FALSE, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_PRIMARY, HINIT_FILE, Hive, _CMHIVE::Hive, HSTORAGE_TYPE, HvGetCell, HvGetCellType, HvReallocateCell(), KEY_COMP_NAME, KEY_HIVE_ENTRY, _CM_KEY_REFERENCE::KeyCell, _CELL_DATA::_u::KeyIndex, _CELL_DATA::_u::KeyNode, _CM_KEY_INDEX::List, _CM_KEY_FAST_INDEX::List, Name, _CM_KEY_NODE::Name, _CM_KEY_NODE::NameLength, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _CM_KEY_NODE::Parent, PHCELL_INDEX, PROTECTED_POOL, _HBASE_BLOCK::RootCell, _CM_KEY_INDEX::Signature, _CM_KEY_NODE::SubKeyCounts, _CM_KEY_NODE::SubKeyLists, TRUE, and _CELL_DATA::u.

Referenced by NtRestoreKey().

    00104                    :
    00105
    00106     This copies the data from an on-disk hive into the registry.  The file
    00107     is not loaded into the registry, and the system will NOT be using
    00108     the source file after the call returns.
    00109
    00110     If the flag REG_WHOLE_HIVE_VOLATILE is not set, the given key is replaced
    00111     by the root of the hive file.  The root's name is changed to the name
    00112     of the given key.
    00113
    00114     If the flag REG_WHOLE_HIVE_VOLATILE is set, a volatile hive is created,
    00115     the hive file is copied into it, and the resulting hive is linked to
    00116     the master hive.  The given key must be in the master hive.  (Usually
    00117     will be \Registry\User)
    00118
    00119     If the flag REG_REFRESH_HIVE is set (must be only flag) then the
    00120     the Hive will be restored to its state as of the last flush.
    00121     (The hive must be marked NOLAZY_FLUSH, and the caller must have
    00122      TCB privilege, and the handle must point to the root of the hive.
    00123      If the refresh fails, the hive will be corrupt, and the system
    00124      will bugcheck.)
    00125
    00126     If the flag REG_FORCE_RESTORE is set, the restore operation is done even
    00127     if there areopen handles underneath the key we are restoring to.
    00128
    00129 Arguments:
    00130
    00131     Hive - supplies a pointer to the hive control structure for the hive
    00132
    00133     Cell - supplies index of node at root of tree to restore into
    00134
    00135     FileHandle - handle of the file to read from.
    00136
    00137 Return Value:
    00138
    00139     NTSTATUS - Result code from call, among the following:
    00140
    00141         <TBS>
    00142
    00143 --*/
    00144 {
    00145     NTSTATUS    status;
    00146     PCELL_DATA  ptar;
    00147     PCELL_DATA  psrc;
    00148     PCMHIVE     TmpCmHive;
    00149     HCELL_INDEX newroot;
    00150     HCELL_INDEX newcell;
    00151     HCELL_INDEX parent;
    00152     HCELL_INDEX list;
    00153     ULONG       count;
    00154     ULONG       i;
    00155     ULONG       j;
    00156     LONG        size;
    00157     PHHIVE      Hive;
    00158     HCELL_INDEX Cell;
    00159     HSTORAGE_TYPE Type;
    00160     ULONG       NumberLeaves;
    00161     PHCELL_INDEX LeafArray;
    00162     PCM_KEY_INDEX Leaf;
    00163     PCM_KEY_FAST_INDEX FastLeaf;
    00164
    00165     PAGED_CODE();
    00166     CMLOG(CML_MAJOR, CMS_SAVRES) {
    00167         KdPrint(("CmRestoreKey:\n"));
    00168         KdPrint(("\tKCB=%08lx\n",KeyControlBlock));
    00169         KdPrint(("\tFileHandle=%08lx\n",FileHandle));
    00170     }
    00171
    00172     if (Flags & REG_REFRESH_HIVE) {
    00173         if ((Flags & ~REG_REFRESH_HIVE) != 0) {
    00174             //
    00175             // Refresh must be alone
    00176             //
    00177             return STATUS_INVALID_PARAMETER;
    00178         }
    00179     }
    00180
    00181     //
    00182     // If they want to do WHOLE_HIVE_VOLATILE, it's a completely different API.
    00183     //
    00184     if (Flags & REG_WHOLE_HIVE_VOLATILE) {
    00185         return(CmpLoadHiveVolatile(KeyControlBlock, FileHandle));
    00186     }
    00187
    00188     //
    00189     // If they want to do REFRESH_HIVE, that's a completely different api too.
    00190     //
    00191     if (Flags & REG_REFRESH_HIVE) {
    00192         CmpLockRegistryExclusive();
    00193         status = CmpRefreshHive(KeyControlBlock);
    00194         CmpUnlockRegistry();
    00195         return status;
    00196     }
    00197
    00198     Hive = KeyControlBlock->KeyHive;
    00199     Cell = KeyControlBlock->KeyCell;
    00200
    00201     //
    00202     // Disallow attempts to "restore" the master hive
    00203     //
    00204     if (Hive == &CmpMasterHive->Hive) {
    00205         return STATUS_ACCESS_DENIED;
    00206     }
    00207
    00208     CmpLockRegistryExclusive();
    00209
    00210     //
    00211     // Make sure this key has not been deleted
    00212     //
    00213     if (KeyControlBlock->Delete) {
    00214         CmpUnlockRegistry();
    00215         return(STATUS_CANNOT_DELETE);
    00216     }
    00217
    00218     DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    00219
    00220     //
    00221     // Check for any open handles underneath the key we are restoring to.
    00222     //
    00223     if (CmpSearchForOpenSubKeys(KeyControlBlock,(Flags&REG_FORCE_RESTORE)?SearchAndDeref:SearchIfExist) != 0) {
    00224
    00225         //
    00226         // Cannot restore over a subtree with open handles in it, or the open handles to subkeys
    00227         // successfully marked as closed.
    00228         //
    00229
    00230         CmpUnlockRegistry();
    00231         return(STATUS_CANNOT_DELETE);
    00232     }
    00233
    00234     //
    00235     // Make sure this is the only handle open for this key
    00236     //
    00237     if (KeyControlBlock->RefCount != 1 && !(Flags&REG_FORCE_RESTORE)) {
    00238         CmpUnlockRegistry();
    00239         return(STATUS_CANNOT_DELETE);
    00240     }
    00241
    00242     ptar = HvGetCell(Hive, Cell);
    00243
    00244     //
    00245     // The subtree the caller wants does not exactly match a
    00246     // subtree.  Make a temporary hive, load the file into it,
    00247     // tree copy the temporary to the active, and free the temporary.
    00248     //
    00249
    00250     //
    00251     // Create the temporary hive
    00252     //
    00253     status = CmpInitializeHive(&TmpCmHive,
    00254                            HINIT_FILE,
    00255                            0,
    00256                            HFILE_TYPE_PRIMARY,
    00257                            NULL,
    00258                            FileHandle,
    00259                            NULL,
    00260                            NULL,
    00261                            NULL,
    00262                            NULL);
    00263
    00264     if (!NT_SUCCESS(status)) {
    00265         goto ErrorExit1;
    00266     }
    00267
    00268     //
    00269     // Create a new target root, under which we will copy the new tree
    00270     //
    00271     if (ptar->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
    00272         parent = HCELL_NIL;                         // root of hive, so parent is NIL
    00273     } else {
    00274         parent = ptar->u.KeyNode.Parent;
    00275     }
    00276
    00277     newroot = CmpCopyKeyPartial(&(TmpCmHive->Hive),
    00278                                 TmpCmHive->Hive.BaseBlock->RootCell,
    00279                                 Hive,
    00280                                 parent,
    00281                                 TRUE);
    00282     if (newroot == HCELL_NIL) {
    00283         status = STATUS_INSUFFICIENT_RESOURCES;
    00284         goto ErrorExit2;
    00285     }
    00286
    00287     //
    00288     // newroot has all the correct stuff, except that it has the
    00289     // source root's name, when it needs to have the target root's.
    00290     // So edit its name.
    00291     //
    00292     psrc = HvGetCell(Hive, Cell);
    00293     ptar = HvGetCell(Hive, newroot);
    00294     size = FIELD_OFFSET(CM_KEY_NODE, Name) + psrc->u.KeyNode.NameLength;
    00295
    00296     //
    00297     // make sure that new root has correct amount of space
    00298     // to hold name from old root
    00299     //
    00300     newcell = HvReallocateCell(Hive, newroot, size);
    00301     if (newcell == HCELL_NIL) {
    00302         status = STATUS_INSUFFICIENT_RESOURCES;
    00303         goto ErrorExit2;
    00304     }
    00305     newroot = newcell;
    00306     ptar = HvGetCell(Hive, newroot);
    00307
    00308     status = STATUS_SUCCESS;
    00309
    00310     RtlMoveMemory((PVOID)&(ptar->u.KeyNode.Name[0]),
    00311                   (PVOID)&(psrc->u.KeyNode.Name[0]),
    00312                   psrc->u.KeyNode.NameLength);
    00313
    00314     ptar->u.KeyNode.NameLength = psrc->u.KeyNode.NameLength;
    00315     if (psrc->u.KeyNode.Flags & KEY_COMP_NAME) {
    00316         ptar->u.KeyNode.Flags |= KEY_COMP_NAME;
    00317     } else {
    00318         ptar->u.KeyNode.Flags &= ~KEY_COMP_NAME;
    00319     }
    00320
    00321     //
    00322     // newroot is now ready to have subtree copied under it, do tree copy
    00323     //
    00324     if (CmpCopyTree(&(TmpCmHive->Hive),
    00325                     TmpCmHive->Hive.BaseBlock->RootCell,
    00326                     Hive,
    00327                     newroot) == FALSE)
    00328     {
    00329         status = STATUS_INSUFFICIENT_RESOURCES;
    00330         goto ErrorExit2;
    00331     }
    00332
    00333     //
    00334     // The new root and the tree under it now look the way we want.
    00335     //
    00336
    00337     //
    00338     // Swap the new tree in for the old one.
    00339     //
    00340     ptar = HvGetCell(Hive, Cell);
    00341     parent = ptar->u.KeyNode.Parent;
    00342
    00343     if (ptar->u.KeyNode.Flags & KEY_HIVE_ENTRY) {
    00344
    00345         //
    00346         // root is actually the root of the hive.  parent doesn't
    00347         // refer to it via a child list, but rather with an inter hive
    00348         // pointer.  also, must update base block
    00349         //
    00350         ptar = HvGetCell( (&(CmpMasterHive->Hive)), parent);
    00351         ptar->u.KeyNode.ChildHiveReference.KeyCell = newroot;
    00352         ptar = HvGetCell(Hive, newroot);
    00353         ptar->u.KeyNode.Parent = parent;
    00354         Hive->BaseBlock->RootCell = newroot;
    00355
    00356
    00357     } else {
    00358
    00359         //
    00360         //  Notice that new root is *always* name of existing target,
    00361         //      therefore, even in b-tree, old and new cell can share
    00362         //      the same reference slot in the parent.  So simply edit
    00363         //      the new cell_index on the top of the old.
    00364         //
    00365         ptar = HvGetCell(Hive, parent);
    00366         Type = HvGetCellType(Cell);
    00367         list = ptar->u.KeyNode.SubKeyLists[Type];
    00368         count = ptar->u.KeyNode.SubKeyCounts[Type];
    00369
    00370         ptar = HvGetCell(Hive, list);
    00371         if (ptar->u.KeyIndex.Signature == CM_KEY_INDEX_ROOT) {
    00372             NumberLeaves = ptar->u.KeyIndex.Count;
    00373             LeafArray = &ptar->u.KeyIndex.List[0];
    00374         } else {
    00375             NumberLeaves = 1;
    00376             LeafArray = &list;
    00377         }
    00378
    00379         //
    00380         // Look in each leaf for the HCELL_INDEX we need to replace
    00381         //
    00382         for (i = 0; i < NumberLeaves; i++) {
    00383             Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafArray[i]);
    00384             if (Leaf->Signature == CM_KEY_FAST_LEAF) {
    00385                 FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
    00386                 for (j=0; j < FastLeaf->Count; j++) {
    00387                     if (FastLeaf->List[j].Cell == Cell) {
    00388                         FastLeaf->List[j].Cell = newroot;
    00389                         goto FoundCell;
    00390                     }
    00391                 }
    00392             } else {
    00393                 for (j=0; j < Leaf->Count; j++) {
    00394                     if (Leaf->List[j] == Cell) {
    00395
    00396                         Leaf->List[j] = newroot;
    00397                         goto FoundCell;
    00398                     }
    00399                 }
    00400             }
    00401         }
    00402         ASSERT(FALSE);      //  implies we didn't find it
    00403                         //  we should never get here
    00404     }
    00405
    00406 FoundCell:
    00407
    00408
    00409     //
    00410     // Fix up the key control block to point to the new root
    00411     //
    00412     KeyControlBlock->KeyCell = newroot;
    00413     KeyControlBlock->KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, newroot);
    00414
    00415     //
    00416     // Kcb has changed, update the cache information.
    00417     // Registry locked exclusively, no need for KCB lock.
    00418     //
    00419     ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    00420
    00421     CmpCleanUpKcbValueCache(KeyControlBlock);
    00422
    00423     if (KeyControlBlock->ExtFlags & CM_KCB_SUBKEY_HINT) {
    00424         //
    00425         // Now free the HintIndex allocation
    00426         //
    00427         ExFreePoolWithTag(KeyControlBlock->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL);
    00428     }
    00429
    00430     KeyControlBlock->ValueCache.Count = KeyControlBlock->KeyNode->ValueList.Count;
    00431     KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) (KeyControlBlock->KeyNode->ValueList.List);
    00432     KeyControlBlock->Flags = KeyControlBlock->KeyNode->Flags;
    00433     KeyControlBlock->Security = KeyControlBlock->KeyNode->Security;
    00434
    00435     KeyControlBlock->ExtFlags = 0;
    00436
    00437     //
    00438     // Delete the old subtree and it's root cell
    00439     //
    00440     CmpDeleteTree(Hive, Cell);
    00441     CmpFreeKeyByCell(Hive, Cell, FALSE);
    00442
    00443     //
    00444     // Report the notify event
    00445     //
    00446     CmpReportNotify(KeyControlBlock,
    00447                     KeyControlBlock->KeyHive,
    00448                     KeyControlBlock->KeyCell,
    00449                     REG_NOTIFY_CHANGE_NAME);
    00450
    00451
    00452     //
    00453     // Free the temporary hive
    00454     //
    00455     CmpDestroyTemporaryHive(TmpCmHive);
    00456
    00457     //
    00458     // We've given user chance to log on, so turn on quota
    00459     //
    00460     if (CmpProfileLoaded == FALSE) {
    00461         CmpProfileLoaded = TRUE;
    00462         CmpSetGlobalQuotaAllowed();
    00463     }
    00464
    00465     DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    00466     CmpUnlockRegistry();
    00467     return status;
    00468
    00469
    00470     //
    00471     // Error exits
    00472     //
    00473 ErrorExit2:
    00474     CmpDestroyTemporaryHive(TmpCmHive);
    00475 ErrorExit1:
    00476     DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    00477     CmpUnlockRegistry();
    00478
    00479     return status;
    00480 }

NTSTATUS CmSaveKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN HANDLE | FileHandle
| ) |

Definition at line 862 of file cmsavres.c.

References ASSERT, _HHIVE::BaseBlock, Cell, CM_WRAP_LIMIT, CML_FLOW, CML_MAJOR, CMLOG, CmpCopyKeyPartial(), CmpCopyTree, CmpCreateTemporaryHive(), CmpDestroyTemporaryHive(), CmpGlobalQuotaAllowed, CmpGlobalQuotaUsed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpMasterHive, CmpSaveKeyByFileCopy(), CmpUnlockRegistry(), CMS_SAVRES, DCmCheckRegistry, _HHIVE::DirtyCount, FALSE, _CMHIVE::FileHandles, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_EXTERNAL, Hive, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HvGetCell, HvWriteHive(), _CELL_DATA::_u::KeyNode, NTSTATUS(), NULL, PAGED_CODE, _HBASE_BLOCK::RootCell, TRUE, _CELL_DATA::u, and USHORT.

Referenced by NtSaveKey().

    00868                    :
    00869
    00870 Arguments:
    00871
    00872     KeyControlBlock - pointer to the KCB that describes the key
    00873
    00874     FileHandle - handle of the file to dump to.
    00875
    00876 Return Value:
    00877
    00878     NTSTATUS - Result code from call, among the following:
    00879
    00880         <TBS>
    00881
    00882 --*/
    00883 {
    00884     NTSTATUS    status;
    00885     PCELL_DATA  proot;
    00886     USHORT      flags;
    00887     PCMHIVE     TmpCmHive;
    00888     PCMHIVE     CmHive;
    00889     HCELL_INDEX newroot;
    00890     PHHIVE Hive;
    00891     HCELL_INDEX Cell;
    00892     ULONG OldQuotaAllowed;
    00893     ULONG OldQuotaWarning;
    00894 #if DBG
    00895     ULONG OldQuotaUsed;
    00896 #endif
    00897
    00898     PAGED_CODE();
    00899     CMLOG(CML_MAJOR, CMS_SAVRES) {
    00900         KdPrint(("CmSaveKey:\n"));
    00901         KdPrint(("\tKCB=%08lx",KeyControlBlock));
    00902         KdPrint(("\tFileHandle=%08lx\n",FileHandle));
    00903     }
    00904
    00905     //
    00906     // Disallow attempts to "save" the master hive
    00907     //
    00908     Hive = KeyControlBlock->KeyHive;
    00909     Cell = KeyControlBlock->KeyCell;
    00910
    00911     if (Hive == &CmpMasterHive->Hive) {
    00912         return STATUS_ACCESS_DENIED;
    00913     }
    00914
    00915     CmpLockRegistryExclusive();
    00916
    00917     if (KeyControlBlock->Delete) {
    00918         CmpUnlockRegistry();
    00919         return STATUS_KEY_DELETED;
    00920     }
    00921
    00922     DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    00923
    00924     if ( (Hive->HiveFlags & HIVE_NOLAZYFLUSH) &&
    00925          (Hive->DirtyCount != 0))
    00926     {
    00927         //
    00928         // It's a NOLAZY hive, and there's some dirty data, so writing
    00929         // out a snapshot of what's in memory will not give the caller
    00930         // consistent user data.  Therefore, copy the on disk image
    00931         // instead of the memory image
    00932         //
    00933
    00934         //
    00935         // Note that this will generate weird results if the key
    00936         // being saved is not the root of the hive, since the
    00937         // resulting file will always be a copy of the entire hive, not
    00938         // just the subtree they asked for.
    00939         //
    00940         status = CmpSaveKeyByFileCopy((PCMHIVE)Hive, FileHandle);
    00941         CmpUnlockRegistry();
    00942         return status;
    00943     }
    00944
    00945     proot = HvGetCell(Hive, Cell);
    00946     flags = proot->u.KeyNode.Flags;
    00947
    00948
    00949     //
    00950     // Always try to copy the hive and write it out.  This has the
    00951     // effect of compressing out unused free storage.
    00952     // If there isn't space, and the savekey is of the root of the
    00953     // hive, then just write it out directly.  (i.e. don't fail on
    00954     // a whole hive restore just because we're out of memory.)
    00955     //
    00956     CMLOG(CML_FLOW, CMS_SAVRES) KdPrint(("\tSave of partial hive\n"));
    00957
    00958     //
    00959     // The subtree the caller wants does not exactly match a
    00960     // subtree.  Make a temporary hive, tree copy the source
    00961     // to temp, write out the temporary, free the temporary.
    00962     //
    00963
    00964     //
    00965     // temporarily disable registry quota as we will be giving this memory back immediately!
    00966     //
    00967     OldQuotaAllowed = CmpGlobalQuotaAllowed;
    00968     OldQuotaWarning = CmpGlobalQuotaWarning;
    00969     CmpGlobalQuotaAllowed = CM_WRAP_LIMIT;
    00970     CmpGlobalQuotaWarning = CM_WRAP_LIMIT;
    00971
    00972 #if DBG
    00973     OldQuotaUsed = CmpGlobalQuotaUsed;
    00974 #endif
    00975
    00976     //
    00977     // Create the temporary hive
    00978     //
    00979
    00980     TmpCmHive = CmpCreateTemporaryHive(FileHandle);
    00981     if (TmpCmHive == NULL) {
    00982         status =  STATUS_INSUFFICIENT_RESOURCES;
    00983         goto ErrorInsufficientResources;
    00984     }
    00985
    00986     //
    00987     // Create a root cell, mark it as such
    00988     //
    00989
    00990     newroot = CmpCopyKeyPartial(
    00991                 Hive,
    00992                 Cell,
    00993                 &(TmpCmHive->Hive),
    00994                 HCELL_NIL,          // will force KEY_HIVE_ENTRY set
    00995                 TRUE);
    00996     if (newroot == HCELL_NIL) {
    00997         status = STATUS_INSUFFICIENT_RESOURCES;
    00998         goto ErrorInsufficientResources;
    00999     }
    01000     TmpCmHive->Hive.BaseBlock->RootCell = newroot;
    01001
    01002     //
    01003     // Do a tree copy
    01004     //
    01005     if (CmpCopyTree(Hive, Cell, &(TmpCmHive->Hive), newroot) == FALSE) {
    01006         status = STATUS_INSUFFICIENT_RESOURCES;
    01007         goto ErrorInsufficientResources;
    01008     }
    01009
    01010     //
    01011     // Write the file
    01012     //
    01013     TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = FileHandle;
    01014     status = HvWriteHive(&(TmpCmHive->Hive));
    01015     TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = NULL;
    01016
    01017     //
    01018     // Error exits
    01019     //
    01020 ErrorInsufficientResources:
    01021
    01022     //
    01023     // Free the temporary hive
    01024     //
    01025     if (TmpCmHive != NULL) {
    01026         CmpDestroyTemporaryHive(TmpCmHive);
    01027     }
    01028
    01029 #if DBG
    01030     //
    01031     // Sanity check: when this assert fires, we have leaks in the copy routine.
    01032     //
    01033     ASSERT( OldQuotaUsed == CmpGlobalQuotaUsed );
    01034 #endif
    01035
    01036     //
    01037     // Set global quota back to what it was.
    01038     //
    01039     CmpGlobalQuotaAllowed = OldQuotaAllowed;
    01040     CmpGlobalQuotaWarning = OldQuotaWarning;
    01041     DCmCheckRegistry(CONTAINING_RECORD(Hive, CMHIVE, Hive));
    01042     CmpUnlockRegistry();
    01043     return status;
    01044 }

NTSTATUS CmSaveMergedKeys | ( | IN PCM_KEY_CONTROL_BLOCK | HighPrecedenceKcb,
|  | IN PCM_KEY_CONTROL_BLOCK | LowPrecedenceKcb,
|  | IN HANDLE | FileHandle
| ) |

Definition at line 1047 of file cmsavres.c.

References ASSERT, _HHIVE::BaseBlock, CM_WRAP_LIMIT, CML_FLOW, CML_MAJOR, CMLOG, CmpCopyKeyPartial(), CmpCopyTree, CmpCreateTemporaryHive(), CmpDestroyTemporaryHive(), CmpGlobalQuotaAllowed, CmpGlobalQuotaUsed, CmpGlobalQuotaWarning, CmpLockRegistryExclusive(), CmpMergeKeyValues(), CmpMergeTrees, CmpUnlockRegistry(), CMS_SAVRES, DCmCheckRegistry, _HHIVE::DirtyCount, FALSE, _CMHIVE::FileHandles, _CM_KEY_NODE::Flags, HCELL_INDEX, HCELL_NIL, HFILE_TYPE_EXTERNAL, Hive, _CMHIVE::Hive, HIVE_NOLAZYFLUSH, _HHIVE::HiveFlags, HvGetCell, HvWriteHive(), _CELL_DATA::_u::KeyNode, NTSTATUS(), NULL, PAGED_CODE, _HBASE_BLOCK::RootCell, TRUE, _CELL_DATA::u, and USHORT.

Referenced by NtSaveMergedKeys().

    01054                    :
    01055
    01056 Arguments:
    01057
    01058     HighPrecedenceKcb - pointer to the KCB that describes the High precedence key
    01059                         (the one that wins in a duplicate key case)
    01060
    01061     LowPrecedenceKcb - pointer to the KCB that describes the Low precedence key
    01062                         (the one that gets overwritten in a duplicate key case)
    01063
    01064     FileHandle - handle of the file to dump to.
    01065
    01066 Return Value:
    01067
    01068     NTSTATUS - Result code from call, among the following:
    01069
    01070         <TBS>
    01071
    01072 --*/
    01073 {
    01074     NTSTATUS    status;
    01075     PCELL_DATA  proot;
    01076     USHORT      flags;
    01077     PCMHIVE     TmpCmHive;
    01078     HCELL_INDEX newroot;
    01079     PHHIVE HighHive;
    01080     PHHIVE LowHive;
    01081     HCELL_INDEX HighCell;
    01082     HCELL_INDEX LowCell;
    01083     ULONG OldQuotaAllowed;
    01084     ULONG OldQuotaWarning;
    01085     PCM_KEY_NODE HighNode,LowNode;
    01086 #if DBG
    01087     ULONG OldQuotaUsed;
    01088 #endif
    01089
    01090     PAGED_CODE();
    01091     CMLOG(CML_MAJOR, CMS_SAVRES) {
    01092         KdPrint(("CmSaveMergedKeys:\n"));
    01093         KdPrint(("\tHighKCB=%08lx",HighPrecedenceKcb));
    01094         KdPrint(("\tLowKCB=%08lx",LowPrecedenceKcb));
    01095         KdPrint(("\tFileHandle=%08lx\n",FileHandle));
    01096     }
    01097
    01098     //
    01099     // Disallow attempts to "merge" keys located in the same hive
    01100     // A brutal way to avoid recursivity
    01101     //
    01102     HighHive = HighPrecedenceKcb->KeyHive;
    01103     HighCell = HighPrecedenceKcb->KeyCell;
    01104     LowHive = LowPrecedenceKcb->KeyHive;
    01105     LowCell = LowPrecedenceKcb->KeyCell;
    01106
    01107     if (LowHive  == HighHive ) {
    01108         return STATUS_INVALID_PARAMETER;
    01109     }
    01110
    01111     CmpLockRegistryExclusive();
    01112
    01113     if (HighPrecedenceKcb->Delete || LowPrecedenceKcb->Delete) {
    01114         //
    01115         // Unlock the registry and fail if one of the keys are marked as deleted
    01116         //
    01117         CmpUnlockRegistry();
    01118         return STATUS_KEY_DELETED;
    01119     }
    01120
    01121     DCmCheckRegistry(CONTAINING_RECORD(HighHive, CMHIVE, Hive));
    01122     DCmCheckRegistry(CONTAINING_RECORD(LowHive, CMHIVE, Hive));
    01123
    01124
    01125     if( ((HighHive->HiveFlags & HIVE_NOLAZYFLUSH) && (HighHive->DirtyCount != 0)) ||
    01126         ((LowHive->HiveFlags & HIVE_NOLAZYFLUSH) && (LowHive->DirtyCount != 0)) ) {
    01127         //
    01128         // Reject the call when one of the hives is a NOLAZY hive and there's
    01129         // some dirty data. Another alternative will be to save only one of the
    01130         // trees (if a valid one exists) or an entire hive (see CmSaveKey)
    01131         //
    01132         status =  STATUS_INVALID_PARAMETER;
    01133         CmpUnlockRegistry();
    01134         return status;
    01135     }
    01136
    01137     proot = HvGetCell(LowHive, LowCell);
    01138     flags = proot->u.KeyNode.Flags;
    01139
    01140
    01141     CMLOG(CML_FLOW, CMS_SAVRES) KdPrint(("\tCopy of partial HighHive\n"));
    01142
    01143     //
    01144     // Make a temporary hive, tree copy the key subtree from
    01145     // HighHive hive to temp, tree-merge with the key subtree from
    01146     // LowHive hive, write out the temporary, free the temporary.
    01147     // Always write the HighHive subtree first, so its afterwise
    01148     // only add new keys/values
    01149     //
    01150
    01151     //
    01152     // temporarily disable registry quota as we will be giving this memory back immediately!
    01153     //
    01154     OldQuotaAllowed = CmpGlobalQuotaAllowed;
    01155     OldQuotaWarning = CmpGlobalQuotaWarning;
    01156     CmpGlobalQuotaAllowed = CM_WRAP_LIMIT;
    01157     CmpGlobalQuotaWarning = CM_WRAP_LIMIT;
    01158
    01159 #if DBG
    01160     OldQuotaUsed = CmpGlobalQuotaUsed;
    01161 #endif
    01162
    01163     //
    01164     // Create the temporary hive
    01165     //
    01166
    01167     TmpCmHive = CmpCreateTemporaryHive(FileHandle);
    01168     if (TmpCmHive == NULL) {
    01169         status =  STATUS_INSUFFICIENT_RESOURCES;
    01170         goto ErrorInsufficientResources;
    01171     }
    01172
    01173     //
    01174     // Create a root cell, mark it as such
    01175     //
    01176
    01177     newroot = CmpCopyKeyPartial(
    01178                 HighHive,
    01179                 HighCell,
    01180                 &(TmpCmHive->Hive),
    01181                 HCELL_NIL,          // will force KEY_HIVE_ENTRY set
    01182                 TRUE);
    01183     if (newroot == HCELL_NIL) {
    01184         status = STATUS_INSUFFICIENT_RESOURCES;
    01185         goto ErrorInsufficientResources;
    01186     }
    01187     TmpCmHive->Hive.BaseBlock->RootCell = newroot;
    01188
    01189     //
    01190     // Do a tree copy. Copy the HighCell tree from HighHive first.
    01191     //
    01192     if (CmpCopyTree(HighHive, HighCell, &(TmpCmHive->Hive), newroot) == FALSE) {
    01193         status = STATUS_INSUFFICIENT_RESOURCES;
    01194         goto ErrorInsufficientResources;
    01195     }
    01196
    01197     //
    01198     // Merge the values in the root node of the merged subtrees
    01199     //
    01200     LowNode = (PCM_KEY_NODE)HvGetCell(LowHive, LowCell);
    01201     HighNode = (PCM_KEY_NODE)HvGetCell(&(TmpCmHive->Hive),newroot);
    01202
    01203     if (CmpMergeKeyValues(LowHive, LowCell, LowNode, &(TmpCmHive->Hive), newroot, HighNode) == FALSE ){
    01204         status = STATUS_INSUFFICIENT_RESOURCES;
    01205         goto ErrorInsufficientResources;
    01206     }
    01207
    01208     CMLOG(CML_FLOW, CMS_SAVRES) KdPrint(("\tMerge partial LowHive over the HighHive\n"));
    01209
    01210     //
    01211     // Merge the two trees. A Merge operation is a sync that obeys
    01212     // the following aditional rules:
    01213     //      1. keys the exist in the taget tree and does not exist
    01214     //      in the source tree remain as they are (don't get deleted)
    01215     //      2. keys the doesn't exist both in the target tree are added
    01216     //      "as they are" from the source tree (always the target tree
    01217     //      has a higher precedence)
    01218     //
    01219     if (CmpMergeTrees(LowHive, LowCell, &(TmpCmHive->Hive), newroot) == FALSE) {
    01220         status = STATUS_INSUFFICIENT_RESOURCES;
    01221         goto ErrorInsufficientResources;
    01222     }
    01223
    01224     //
    01225     // Write the file
    01226     //
    01227     TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = FileHandle;
    01228     status = HvWriteHive(&(TmpCmHive->Hive));
    01229     TmpCmHive->FileHandles[HFILE_TYPE_EXTERNAL] = NULL;
    01230
    01231     //
    01232     // Error exits
    01233     //
    01234 ErrorInsufficientResources:
    01235     //
    01236     // Free the temporary hive
    01237     //
    01238     if (TmpCmHive != NULL) {
    01239         CmpDestroyTemporaryHive(TmpCmHive);
    01240     }
    01241
    01242 #if DBG
    01243     //
    01244     // Sanity check: when this assert fires, we have leaks in the merge routine.
    01245     //
    01246     ASSERT( OldQuotaUsed == CmpGlobalQuotaUsed );
    01247 #endif
    01248     //
    01249     // Set global quota back to what it was.
    01250     //
    01251     CmpGlobalQuotaAllowed = OldQuotaAllowed;
    01252     CmpGlobalQuotaWarning = OldQuotaWarning;
    01253     DCmCheckRegistry(CONTAINING_RECORD(HighHive, CMHIVE, Hive));
    01254     DCmCheckRegistry(CONTAINING_RECORD(LowHive, CMHIVE, Hive));
    01255     CmpUnlockRegistry();
    01256     return status;
    01257 }

NTSTATUS CmSetAcpiHwProfile | ( | IN PPROFILE_ACPI_DOCKING_STATE | DockState,
|  | IN | PCM_ACPI_SELECTION_ROUTINE,
|  | IN PVOID | Context,
|  | OUT PHANDLE | NewProfile,
|  | OUT PBOOLEAN | ProfileChanged
| ) |

Definition at line 805 of file hwprofil.c.

References _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST::Alias, ASSERT, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER, CM_HARDWARE_PROFILE_STR_CCS_CURRENT, CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE, CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO, CM_HARDWARE_PROFILE_STR_DATABASE, CM_HARDWARE_PROFILE_STR_DOCKING_STATE, CM_HP_FLAGS_DUPLICATE, CM_HP_FLAGS_PRISTINE, CM_HP_FLAGS_TRUE_MATCH, CmpAddAcpiAliasEntry(), CmpCloneHwProfile(), CmpFilterAcpiDockingState(), CmpGetAcpiProfileInformation(), CmpMoveBiosAliasTable(), CmSymbolicLinkValueName, _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST::CurrentAliasCount, _CM_HARDWARE_PROFILE_LIST::CurrentProfileCount, ExAllocatePool, ExFreePool(), FALSE, _CM_HARDWARE_PROFILE::Flags, _CM_HARDWARE_PROFILE::FriendlyName, _CM_HARDWARE_PROFILE::Id, L, NT_SUCCESS, NtCreateKey(), NtQueryValueKey(), NtSetValueKey(), NTSTATUS(), NULL, PAGED_CODE, PagedPool, _CM_HARDWARE_PROFILE_LIST::Profile, RtlInitUnicodeString(), _CM_HARDWARE_PROFILE_ACPI_ALIAS::SerialNumber, and TRUE.

Referenced by CmpCreateControlSet(), and IopExecuteHardwareProfileChange().

    00813                    :
    00814
    00815     The ACPI docking state of the machine has changed.
    00816
    00817     Based on the new change calculate the new HW Profile(s) consitent with the
    00818     new ACPI docking state.
    00819
    00820     Pass the list of known profiles to the callers selection routine.
    00821
    00822     Set the new current profile.
    00823
    00824     Patch up any ACPI alias entries if a new profile for this ACPI state has
    00825     been used.
    00826
    00827 Arguments:
    00828
    00829     NewDockStateArray - The list of possible Docking States that we might enter.
    00830
    00831     Select - Call back to select which profile to enter, given the list of
    00832              possible profiles.
    00833
    00834 --*/
    00835 {
    00836     NTSTATUS        status = STATUS_SUCCESS;
    00837     HANDLE          IDConfigDB = NULL;
    00838     HANDLE          HardwareProfile = NULL;
    00839     HANDLE          currentInfo = NULL;
    00840     HANDLE          currentSymLink = NULL;
    00841     HANDLE          parent = NULL;
    00842     WCHAR           nameBuffer[128];
    00843     UNICODE_STRING  name;
    00844     UCHAR           valueBuffer[256];
    00845     ULONG           len;
    00846     ULONG           i;
    00847     ULONG           selectedElement;
    00848     ULONG           profileNum;
    00849     ULONG           currentDockingState;
    00850     ULONG           currentProfileNumber;
    00851     ULONG           disposition;
    00852     ULONG           flags;
    00853     PWCHAR          currentAcpiSN = NULL;
    00854     PCM_HARDWARE_PROFILE_ACPI_ALIAS_LIST  AliasList = NULL;
    00855     PCM_HARDWARE_PROFILE_LIST             ProfileList = NULL;
    00856     PKEY_VALUE_FULL_INFORMATION           value;
    00857     OBJECT_ATTRIBUTES                     attributes;
    00858
    00859     PAGED_CODE ();
    00860
    00861     *ProfileChanged = FALSE;
    00862
    00863     value = (PKEY_VALUE_FULL_INFORMATION) valueBuffer;
    00864
    00865     //
    00866     // Open The Hardware Profile Database
    00867     //
    00868     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_DATABASE);
    00869     InitializeObjectAttributes (&attributes,
    00870                                 &name,
    00871                                 OBJ_CASE_INSENSITIVE,
    00872                                 NULL,
    00873                                 NULL);
    00874
    00875     status = ZwOpenKey (&IDConfigDB,
    00876                         KEY_READ,
    00877                         &attributes);
    00878
    00879     if (!NT_SUCCESS (status)) {
    00880         IDConfigDB = NULL;
    00881         goto Clean;
    00882     }
    00883
    00884     //
    00885     // Obtain the total list of profiles
    00886     //
    00887     status = CmpGetAcpiProfileInformation (IDConfigDB,
    00888                                            &ProfileList,
    00889                                            &AliasList,
    00890                                            nameBuffer,
    00891                                            valueBuffer,
    00892                                            sizeof (valueBuffer));
    00893
    00894     if (!NT_SUCCESS (status)) {
    00895         goto Clean;
    00896     }
    00897
    00898     //
    00899     // Determine the current Dock information.
    00900     //
    00901     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_CCS_CURRENT);
    00902     InitializeObjectAttributes (&attributes,
    00903                                 &name,
    00904                                 OBJ_CASE_INSENSITIVE,
    00905                                 NULL,
    00906                                 NULL);
    00907
    00908     status = ZwOpenKey (&HardwareProfile,
    00909                         KEY_READ,
    00910                         &attributes);
    00911     if (!NT_SUCCESS (status)) {
    00912         HardwareProfile = NULL;
    00913         goto Clean;
    00914     }
    00915     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO);
    00916     InitializeObjectAttributes (&attributes,
    00917                                 &name,
    00918                                 OBJ_CASE_INSENSITIVE,
    00919                                 IDConfigDB,
    00920                                 NULL);
    00921
    00922     status = ZwOpenKey (&currentInfo,
    00923                         KEY_READ,
    00924                         &attributes);
    00925     if (!NT_SUCCESS (status)) {
    00926         currentInfo = NULL;
    00927         goto Clean;
    00928     }
    00929
    00930     //
    00931     // The current Docking State
    00932     //
    00933     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_DOCKING_STATE);
    00934     status = NtQueryValueKey (currentInfo,
    00935                               &name,
    00936                               KeyValueFullInformation,
    00937                               valueBuffer,
    00938                               sizeof (valueBuffer),
    00939                               &len);
    00940
    00941     if (!NT_SUCCESS (status) || (value->Type != REG_DWORD)) {
    00942         status = STATUS_REGISTRY_CORRUPT;
    00943         goto Clean;
    00944     }
    00945     currentDockingState = * (PULONG) ((PUCHAR) value + value->DataOffset);
    00946
    00947     //
    00948     // The current ACPI Serial Number
    00949     //
    00950     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER);
    00951     status = NtQueryValueKey(currentInfo,
    00952                              &name,
    00953                              KeyValueFullInformation,
    00954                              valueBuffer,
    00955                              sizeof (valueBuffer),
    00956                              &len);
    00957
    00958     if (NT_SUCCESS (status) && (value->Type == REG_BINARY)) {
    00959
    00960         currentAcpiSN = ExAllocatePool (PagedPool, value->DataLength);
    00961
    00962         if (NULL == currentAcpiSN) {
    00963             status = STATUS_INSUFFICIENT_RESOURCES;
    00964             goto Clean;
    00965         }
    00966         RtlCopyMemory (currentAcpiSN,
    00967                        (PUCHAR) value + value->DataOffset,
    00968                        value->DataLength);
    00969     } else {
    00970         currentAcpiSN = 0;
    00971     }
    00972
    00973     //
    00974     // The current Profile Number
    00975     //
    00976     RtlInitUnicodeString(&name, L"CurrentConfig");
    00977     status = NtQueryValueKey(IDConfigDB,
    00978                              &name,
    00979                              KeyValueFullInformation,
    00980                              valueBuffer,
    00981                              sizeof (valueBuffer),
    00982                              &len);
    00983
    00984     if (!NT_SUCCESS(status) || (value->Type != REG_DWORD)) {
    00985         status = STATUS_REGISTRY_CORRUPT;
    00986         goto Clean;
    00987     }
    00988     currentProfileNumber = *(PULONG)((PUCHAR)value + value->DataOffset);
    00989
    00990     //
    00991     // Filter the current list of hardware profiles based on the current
    00992     // docking state, the new acpi state, and the acpi alias tables
    00993     //
    00994     status = CmpFilterAcpiDockingState (NewDockState,
    00995                                         currentDockingState,
    00996                                         currentAcpiSN,
    00997                                         currentProfileNumber,
    00998                                         ProfileList,
    00999                                         AliasList);
    01000
    01001     if (!NT_SUCCESS (status)) {
    01002         goto Clean;
    01003     }
    01004
    01005     //
    01006     // Allow the caller a chance to select from the filtered list.
    01007     //
    01008     status = Select (ProfileList, &selectedElement, Context);
    01009
    01010     //
    01011     // If the user selected -1 then he is not interested in selecting any of
    01012     // the profiles.
    01013     //
    01014     if (-1 == selectedElement) {
    01015         ASSERT (STATUS_MORE_PROCESSING_REQUIRED == status);
    01016         goto Clean;
    01017     }
    01018
    01019     if (!NT_SUCCESS (status)) {
    01020         goto Clean;
    01021     }
    01022
    01023     //
    01024     // Fine! We have finally made the new selection.
    01025     // Set it.
    01026     //
    01027
    01028     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE);
    01029     InitializeObjectAttributes (&attributes,
    01030                                 &name,
    01031                                 OBJ_CASE_INSENSITIVE,
    01032                                 NULL,
    01033                                 NULL);
    01034     status = ZwOpenKey (&parent, KEY_READ, &attributes);
    01035     if (!NT_SUCCESS (status)) {
    01036         parent = NULL;
    01037         goto Clean;
    01038     }
    01039
    01040     //
    01041     // How did we get here?
    01042     //
    01043     flags = ProfileList->Profile[selectedElement].Flags;
    01044     profileNum = ProfileList->Profile[selectedElement].Id;
    01045
    01046     //
    01047     // Check for duplicate
    01048     //
    01049     if (flags & CM_HP_FLAGS_DUPLICATE) {
    01050         //
    01051         // If there is a duplicate then we need to adjust the pnp
    01052         // bios alias table.
    01053         //
    01054         // This happens if we booted PnP bios detected docked, and then
    01055         // we received a set state for ACPI as docked, then we have the
    01056         // potential for duplicates.  See Comment in CmpFilterAcpiDockingState
    01057         // for details.
    01058         //
    01059         // We need to find any pnp bios alias entries that match the current
    01060         // state and point them to the duplicate entry.
    01061         //
    01062
    01063         ASSERT (flags & CM_HP_FLAGS_TRUE_MATCH);
    01064         ASSERT (!(flags & CM_HP_FLAGS_PRISTINE));
    01065
    01066         status = CmpMoveBiosAliasTable (IDConfigDB,
    01067                                         currentInfo,
    01068                                         currentProfileNumber,
    01069                                         profileNum,
    01070                                         nameBuffer,
    01071                                         valueBuffer,
    01072                                         sizeof (valueBuffer));
    01073
    01074         if (!NT_SUCCESS (status)) {
    01075             goto Clean;
    01076         }
    01077     }
    01078
    01079     if ((flags & CM_HP_FLAGS_PRISTINE) || (profileNum != currentProfileNumber)){
    01080         //
    01081         // The profile Number Changed or will change.
    01082         //
    01083         *ProfileChanged = TRUE;
    01084
    01085         ASSERT (currentInfo);
    01086         ZwClose (currentInfo);
    01087         currentInfo = NULL;
    01088
    01089         if (flags & CM_HP_FLAGS_PRISTINE) {
    01090             //
    01091             // If the selected profile is pristine then we need to clone.
    01092             //
    01093             ASSERT (!(flags & CM_HP_FLAGS_TRUE_MATCH));
    01094             status = CmpCloneHwProfile (IDConfigDB,
    01095                                         parent,
    01096                                         HardwareProfile,
    01097                                         profileNum,
    01098                                         NewDockState->DockingState,
    01099                                         &HardwareProfile,
    01100                                         &profileNum);
    01101             if (!NT_SUCCESS (status)) {
    01102                 HardwareProfile = 0;
    01103                 goto Clean;
    01104             }
    01105         } else {
    01106             ASSERT (HardwareProfile);
    01107             ZwClose (HardwareProfile);
    01108
    01109             //
    01110             // Open the new profile
    01111             //
    01112             swprintf (nameBuffer, L"%04d\0", profileNum);
    01113             RtlInitUnicodeString (&name, nameBuffer);
    01114             InitializeObjectAttributes (&attributes,
    01115                                         &name,
    01116                                         OBJ_CASE_INSENSITIVE,
    01117                                         parent,
    01118                                         NULL);
    01119             status = ZwOpenKey (&HardwareProfile, KEY_READ, &attributes);
    01120             if (!NT_SUCCESS (status)) {
    01121                 HardwareProfile = NULL;
    01122                 goto Clean;
    01123             }
    01124         }
    01125
    01126         ASSERT (currentProfileNumber != profileNum);
    01127
    01128         //
    01129         // Open the current info for the profile.
    01130         //
    01131         RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO);
    01132         InitializeObjectAttributes (&attributes,
    01133                                     &name,
    01134                                     OBJ_CASE_INSENSITIVE,
    01135                                     IDConfigDB,
    01136                                     NULL);
    01137
    01138         status = NtCreateKey (&currentInfo,
    01139                               KEY_READ | KEY_WRITE,
    01140                               &attributes,
    01141                               0,
    01142                               NULL,
    01143                               REG_OPTION_VOLATILE,
    01144                               &disposition);
    01145
    01146         if (!NT_SUCCESS (status)) {
    01147             currentInfo = NULL;
    01148             goto Clean;
    01149         }
    01150
    01151         //
    01152         // Set CurrentConfig in the Database
    01153         //
    01154         RtlInitUnicodeString(&name, L"CurrentConfig");
    01155         status = NtSetValueKey(IDConfigDB,
    01156                                  &name,
    01157                                  0,
    01158                                  REG_DWORD,
    01159                                  &profileNum,
    01160                                  sizeof (profileNum));
    01161
    01162          if (!NT_SUCCESS(status)) {
    01163             status = STATUS_REGISTRY_CORRUPT;
    01164             goto Clean;
    01165         }
    01166     }
    01167
    01168     //
    01169     // Write the new Docking State to the current Info key
    01170     //
    01171     i = NewDockState->DockingState;
    01172     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_DOCKING_STATE);
    01173     status = ZwSetValueKey (currentInfo,
    01174                             &name,
    01175                             0,
    01176                             REG_DWORD,
    01177                             &i,
    01178                             sizeof (ULONG));
    01179
    01180     //
    01181     // Write the new ACPI information to the current Info key
    01182     //
    01183     RtlInitUnicodeString (&name, CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER);
    01184     status = ZwSetValueKey (currentInfo,
    01185                             &name,
    01186                             0,
    01187                             REG_BINARY,
    01188                             NewDockState->SerialNumber,
    01189                             NewDockState->SerialLength);
    01190
    01191     if (!(flags & CM_HP_FLAGS_TRUE_MATCH)) {
    01192         //
    01193         // Add the alias entry for this profile.
    01194         //
    01195         status = CmpAddAcpiAliasEntry (IDConfigDB,
    01196                                        NewDockState,
    01197                                        profileNum,
    01198                                        nameBuffer,
    01199                                        valueBuffer,
    01200                                        sizeof (valueBuffer),
    01201                                        FALSE); // Don't Prevent Duplication
    01202     }
    01203
    01204     if (profileNum != currentProfileNumber) {
    01205         //
    01206         // Move the symbolic link.
    01207         //
    01208         RtlInitUnicodeString(&name, CM_HARDWARE_PROFILE_STR_CCS_CURRENT);
    01209         InitializeObjectAttributes(&attributes,
    01210                                    &name,
    01211                                    OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
    01212                                    NULL,
    01213                                    NULL);
    01214
    01215         status = NtCreateKey(&currentSymLink,
    01216                              KEY_CREATE_LINK,
    01217                              &attributes,
    01218                              0,
    01219                              NULL,
    01220                              REG_OPTION_OPEN_LINK,
    01221                              &disposition);
    01222
    01223         ASSERT (STATUS_SUCCESS == status);
    01224         ASSERT (REG_OPENED_EXISTING_KEY == disposition);
    01225
    01226         swprintf (nameBuffer,
    01227                   L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\%04d",
    01228                   profileNum);
    01229         RtlInitUnicodeString (&name, nameBuffer);
    01230         status = NtSetValueKey (currentSymLink,
    01231                                 &CmSymbolicLinkValueName,
    01232                                 0,
    01233                                 REG_LINK,
    01234                                 name.Buffer,
    01235                                 name.Length);
    01236
    01237         ASSERT (STATUS_SUCCESS == status);
    01238     }
    01239
    01240
    01241 Clean:
    01242     if (NT_SUCCESS (status)) {
    01243         // NB more process required is not a success code.
    01244         *NewProfile = HardwareProfile;
    01245     } else if (NULL != HardwareProfile) {
    01246         ZwClose (HardwareProfile);
    01247     }
    01248
    01249     if (NULL != IDConfigDB) {
    01250         ZwClose (IDConfigDB);
    01251     }
    01252     if (NULL != currentInfo) {
    01253         ZwClose (currentInfo);
    01254     }
    01255     if (NULL != parent) {
    01256         ZwClose (parent);
    01257     }
    01258     if (NULL != currentAcpiSN) {
    01259         ExFreePool (currentAcpiSN);
    01260     }
    01261     if (NULL != ProfileList) {
    01262         for (i = 0; i < ProfileList->CurrentProfileCount; i++) {
    01263             if (ProfileList->Profile[i].FriendlyName) {
    01264                 ExFreePool (ProfileList->Profile[i].FriendlyName);
    01265             }
    01266         }
    01267         ExFreePool (ProfileList);
    01268     }
    01269     if (NULL != AliasList) {
    01270         for (i = 0; i < AliasList->CurrentAliasCount; i++) {
    01271             if (AliasList->Alias[i].SerialNumber) {
    01272                 ExFreePool (AliasList->Alias[i].SerialNumber);
    01273             }
    01274         }
    01275         ExFreePool (AliasList);
    01276     }
    01277
    01278     return status;
    01279 }

NTSTATUS CmSetLastWriteTimeKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PLARGE_INTEGER | LastWriteTime
| ) |

Definition at line 1841 of file cmapi.c.

References Cell, CML_WORKER, CMLOG, CmpLockRegistryExclusive(), CmpUnlockRegistry(), CMS_CM, HCELL_INDEX, Hive, HvMarkCellDirty(), _CM_KEY_NODE::LastWriteTime, NTSTATUS(), and TRUE.

Referenced by NtSetInformationKey().

    01847                    :
    01848
    01849     The LastWriteTime associated with a key node can be set with
    01850     CmSetLastWriteTimeKey
    01851
    01852 Arguments:
    01853
    01854     KeyControlBlock - pointer to kcb for the key to operate on
    01855
    01856     LastWriteTime - new time for key
    01857
    01858 Return Value:
    01859
    01860     NTSTATUS - Result code from call, among the following:
    01861
    01862         <TBS>
    01863
    01864 --*/
    01865 {
    01866     PCM_KEY_NODE parent;
    01867     PHHIVE      Hive;
    01868     HCELL_INDEX Cell;
    01869     NTSTATUS    status = STATUS_SUCCESS;
    01870
    01871     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmSetLastWriteTimeKey\n"));
    01872
    01873     CmpLockRegistryExclusive();
    01874
    01875     //
    01876     // Check that we are not being asked to modify a key
    01877     // that has been deleted
    01878     //
    01879     if (KeyControlBlock->Delete == TRUE) {
    01880         status = STATUS_KEY_DELETED;
    01881         goto Exit;
    01882     }
    01883
    01884     Hive = KeyControlBlock->KeyHive;
    01885     Cell = KeyControlBlock->KeyCell;
    01886     parent = KeyControlBlock->KeyNode;
    01887     if (! HvMarkCellDirty(Hive, Cell)) {
    01888         status = STATUS_NO_LOG_SPACE;
    01889         goto Exit;
    01890     }
    01891
    01892     parent->LastWriteTime = *LastWriteTime;
    01893
    01894 Exit:
    01895     CmpUnlockRegistry();
    01896     return status;
    01897 }

NTSTATUS CmSetValueKey | ( | IN PCM_KEY_CONTROL_BLOCK | KeyControlBlock,
|  | IN PUNICODE_STRING | ValueName,
|  | IN ULONG | Type,
|  | IN PVOID | Data,
|  | IN ULONG | DataSize
| ) |

Definition at line 1087 of file cmapi.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, Cell, CM_KEY_VALUE_SMALL, CM_KEY_VALUE_SPECIAL_SIZE, CML_API, CML_WORKER, CMLOG, CmpCleanUpKcbValueCache(), CmpFindNameInList(), CmpLockRegistry(), CmpLockRegistryExclusive(), CmpMarkAllBinsReadOnly, CmpReportNotify(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpUnlockRegistry(), CMS_CM, CMS_EXCEPTION, CmSymbolicLinkValueName, _CHILD_LIST::Count, _CM_KEY_VALUE::Data, _CM_KEY_VALUE::DataLength, EXCEPTION_EXECUTE_HANDLER, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, HvGetCellType, HvMarkCellDirty(), KeQuerySystemTime(), KEY_SYM_LINK, _CELL_DATA::_u::KeyValue, _CM_KEY_NODE::LastWriteTime, _CHILD_LIST::List, _CM_KEY_NODE::MaxValueDataLen, _CM_KEY_NODE::MaxValueNameLen, NT_SUCCESS, NTSTATUS(), NULL, RtlEqualUnicodeString(), TRUE, _CM_KEY_VALUE::Type, _CELL_DATA::u, _CM_KEY_NODE::ValueList, and ValueName.

Referenced by EhSetValueKey(), and NtSetValueKey().

    01096                    :
    01097
    01098     A value entry may be created or replaced with CmSetValueKey.
    01099
    01100     If a value entry with a Value ID (i.e. name) matching the
    01101     one specified by ValueName exists, it is deleted and replaced
    01102     with the one specified.  If no such value entry exists, a new
    01103     one is created.  NULL is a legal Value ID.  While Value IDs must
    01104     be unique within any given key, the same Value ID may appear
    01105     in many different keys.
    01106
    01107 Arguments:
    01108
    01109     KeyControlBlock - pointer to kcb for the key to operate on
    01110
    01111     ValueName - The unique (relative to the containing key) name
    01112         of the value entry.  May be NULL.
    01113
    01114     Type - The integer type number of the value entry.
    01115
    01116     Data - Pointer to buffer with actual data for the value entry.
    01117
    01118     DataSize - Size of Data buffer.
    01119
    01120
    01121 Return Value:
    01122
    01123     NTSTATUS - Result code from call, among the following:
    01124
    01125         <TBS>
    01126
    01127 --*/
    01128 {
    01129     NTSTATUS    status;
    01130     PCM_KEY_NODE parent;
    01131     HCELL_INDEX oldchild;
    01132     ULONG       count;
    01133     PHHIVE      Hive;
    01134     HCELL_INDEX Cell;
    01135     ULONG       StorageType;
    01136     ULONG       TempData;
    01137     BOOLEAN     found;
    01138     PCELL_DATA  pdata;
    01139     LARGE_INTEGER systemtime;
    01140     ULONG compareSize,mustChange=FALSE;
    01141
    01142     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmSetValueKey\n"));
    01143
    01144     CmpLockRegistry();
    01145     ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL);
    01146
    01147     // Mark the hive as read only
    01148     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01149
    01150     while (TRUE) {
    01151         //
    01152         // Check that we are not being asked to add a value to a key
    01153         // that has been deleted
    01154         //
    01155         if (KeyControlBlock->Delete == TRUE) {
    01156             status = STATUS_KEY_DELETED;
    01157             goto Exit;
    01158         }
    01159
    01160         //
    01161         // Check to see if this is a symbolic link node.  If so caller
    01162         // is only allowed to create/change the SymbolicLinkValue
    01163         // value name
    01164         //
    01165
    01166         if (KeyControlBlock->KeyNode->Flags & KEY_SYM_LINK &&
    01167             (Type != REG_LINK ||
    01168              ValueName == NULL ||
    01169              !RtlEqualUnicodeString(&CmSymbolicLinkValueName, ValueName, TRUE)))
    01170         {
    01171             //
    01172             // Disallow attempts to manipulate any value names under a symbolic link
    01173             // except for the "SymbolicLinkValue" value name or type other than REG_LINK
    01174             //
    01175
    01176             // Mark the hive as read only
    01177             CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01178
    01179             status = STATUS_ACCESS_DENIED;
    01180             goto Exit;
    01181         }
    01182
    01183         //
    01184         // get reference to parent key,
    01185         //
    01186         Hive = KeyControlBlock->KeyHive;
    01187         Cell = KeyControlBlock->KeyCell;
    01188         parent = KeyControlBlock->KeyNode;
    01189
    01190         //
    01191         // try to find an existing value entry by the same name
    01192         //
    01193         count = parent->ValueList.Count;
    01194         found = FALSE;
    01195
    01196         if (count > 0) {
    01197             oldchild = CmpFindNameInList(Hive,
    01198                                          &parent->ValueList,
    01199                                          ValueName,
    01200                                          &pdata,
    01201                                          NULL);
    01202
    01203             if (oldchild != HCELL_NIL) {
    01204                 found = TRUE;
    01205             }
    01206         }
    01207         //
    01208         // Performance Hack:
    01209         // If a Set is asking us to set a key to the current value (IE does this a lot)
    01210         // drop it (and, therefore, the last modified time) on the floor, but return success
    01211         // this stops the page from being dirtied, and us having to flush the registry.
    01212         //
    01213         //
    01214         if (mustChange == TRUE) {
    01215             break; //while
    01216         }
    01217         if ((found) &&
    01218             (Type == pdata->u.KeyValue.Type)) {
    01219
    01220             PCELL_DATA pcmpdata;
    01221
    01222             if (DataSize == (pdata->u.KeyValue.DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE)) {
    01223
    01224                 if (DataSize > 0) {
    01225                     //
    01226                     //check for small values
    01227                     //
    01228                     if (DataSize <= CM_KEY_VALUE_SMALL ) {
    01229                         pcmpdata = (PCELL_DATA)&pdata->u.KeyValue.Data;
    01230                     } else {
    01231                         pcmpdata = HvGetCell(Hive, pdata->u.KeyValue.Data);
    01232                     }
    01233
    01234                     try {
    01235                         compareSize = (ULONG)RtlCompareMemory ((PVOID)pcmpdata,Data,(DataSize & ~CM_KEY_VALUE_SPECIAL_SIZE));
    01236                     } except (EXCEPTION_EXECUTE_HANDLER) {
    01237
    01238                         CMLOG(CML_API, CMS_EXCEPTION) {
    01239                             KdPrint(("!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
    01240                         }
    01241                         status = GetExceptionCode();
    01242                         goto Exit;
    01243                     }
    01244                 }else {
    01245                     compareSize = 0;
    01246                 }
    01247
    01248                 if (compareSize == DataSize) {
    01249                     status = STATUS_SUCCESS;
    01250                     goto Exit;
    01251                 }
    01252             }
    01253
    01254         }
    01255
    01256         //
    01257         // To Get here, we must either be changing a value, or setting a new one
    01258         //
    01259         mustChange=TRUE;
    01260         //
    01261         // We're going through these gyrations so that if someone does come in and try and delete the
    01262         // key we're setting we're safe. Once we know we have to change the key, take the
    01263         // Exclusive (write) lock then restart
    01264         //
    01265         //
    01266         CmpUnlockRegistry();
    01267         CmpLockRegistryExclusive();
    01268
    01269     }// while
    01270
    01271     // It's a different or new value, mark it dirty, since we'll
    01272     // at least set its time stamp
    01273
    01274     if (! HvMarkCellDirty(Hive, Cell)) {
    01275         status = STATUS_NO_LOG_SPACE;
    01276         goto Exit;
    01277     }
    01278
    01279     StorageType = HvGetCellType(Cell);
    01280
    01281     //
    01282     // stash small data if relevent
    01283     //
    01284     TempData = 0;
    01285     if ((DataSize <= CM_KEY_VALUE_SMALL) &&
    01286         (DataSize > 0))
    01287     {
    01288         try {
    01289             RtlMoveMemory(          // yes, move memory, could be 1 byte
    01290                 &TempData,          // at the end of a page.
    01291                 Data,
    01292                 DataSize
    01293                 );
    01294          } except (EXCEPTION_EXECUTE_HANDLER) {
    01295             CMLOG(CML_API, CMS_EXCEPTION) {
    01296                 KdPrint(("!!CmSetValueKey: code:%08lx\n", GetExceptionCode()));
    01297             }
    01298             status = GetExceptionCode();
    01299             goto Exit;
    01300         }
    01301     }
    01302
    01303     if (found) {
    01304
    01305         //
    01306         // ----- Existing Value Entry Path -----
    01307         //
    01308
    01309         //
    01310         // An existing value entry of the specified name exists,
    01311         // set our data into it.
    01312         //
    01313         status = CmpSetValueKeyExisting(Hive,
    01314                                         oldchild,
    01315                                         pdata,
    01316                                         Type,
    01317                                         Data,
    01318                                         DataSize,
    01319                                         StorageType,
    01320                                         TempData);
    01321
    01322     } else {
    01323
    01324         //
    01325         // ----- New Value Entry Path -----
    01326         //
    01327
    01328         //
    01329         // Either there are no existing value entries, or the one
    01330         // specified is not in the list.  In either case, create and
    01331         // fill a new one, and add it to the list
    01332         //
    01333         status = CmpSetValueKeyNew(Hive,
    01334                                    parent,
    01335                                    ValueName,
    01336                                    Type,
    01337                                    Data,
    01338                                    DataSize,
    01339                                    StorageType,
    01340                                    TempData);
    01341     }
    01342
    01343     if (NT_SUCCESS(status)) {
    01344
    01345         if (parent->MaxValueNameLen < ValueName->Length) {
    01346             parent->MaxValueNameLen = ValueName->Length;
    01347         }
    01348
    01349         if (parent->MaxValueDataLen < DataSize) {
    01350             parent->MaxValueDataLen = DataSize;
    01351         }
    01352
    01353         KeQuerySystemTime(&systemtime);
    01354         parent->LastWriteTime = systemtime;
    01355
    01356         //
    01357         // Update the cache, no need for KCB lock as the registry is locked exclusively.
    01358         //
    01359         ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
    01360
    01361         CmpCleanUpKcbValueCache(KeyControlBlock);
    01362
    01363         KeyControlBlock->ValueCache.Count = parent->ValueList.Count;
    01364         KeyControlBlock->ValueCache.ValueList = (ULONG_PTR) parent->ValueList.List;
    01365
    01366         CmpReportNotify(KeyControlBlock,
    01367                         KeyControlBlock->KeyHive,
    01368                         KeyControlBlock->KeyCell,
    01369                         REG_NOTIFY_CHANGE_LAST_SET);
    01370     }
    01371
    01372 Exit:
    01373     CmpUnlockRegistry();
    01374
    01375     // Mark the hive as read only
    01376     CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
    01377
    01378     return status;
    01379 }

NTSTATUS CmUnloadKey | ( | IN PHHIVE | Hive,
|  | IN HCELL_INDEX | Cell,
|  | IN PCM_KEY_CONTROL_BLOCK | Kcb
| ) |

Definition at line 2079 of file cmapi.c.

References ASSERT, _HHIVE::BaseBlock, _REGISTRY_COMMAND::Cell, Cell, _REGISTRY_COMMAND::CmHive, CML_WORKER, CMLOG, CmpDestroyHive(), CmpFree(), CmpLockRegistryExclusive(), CmpSearchForOpenSubKeys(), CmpSearchKeyControlBlockTree(), CmpUnlockRegistry(), CmpWorker(), CMS_CM, _REGISTRY_COMMAND::Command, ExFreePool(), _REGISTRY_COMMAND::Hive, Hive, _CMHIVE::HiveLock, HvFreeHive(), NULL, REG_CMD_FLUSH_KEY, REG_CMD_HIVE_CLOSE, REG_CMD_REMOVE_HIVE_LIST, _HBASE_BLOCK::RootCell, and SearchIfExist.

Referenced by NtUnloadKey().

    02087                    :
    02088
    02089     Unlinks a hive from its location in the registry, closes its file
    02090     handles, and deallocates all its memory.
    02091
    02092     There must be no key control blocks currently referencing the hive
    02093     to be unloaded.
    02094
    02095 Arguments:
    02096
    02097     Hive - Supplies a pointer to the hive control structure for the
    02098            hive to be unloaded
    02099
    02100     Cell - supplies the HCELL_INDEX for the root cell of the hive.
    02101
    02102     Kcb - Supplies the key control block
    02103
    02104 Return Value:
    02105
    02106     NTSTATUS
    02107
    02108 --*/
    02109
    02110 {
    02111     PCMHIVE CmHive;
    02112     REGISTRY_COMMAND Command;
    02113     BOOLEAN Success;
    02114
    02115     CMLOG(CML_WORKER, CMS_CM) KdPrint(("CmUnloadKey\n"));
    02116
    02117     CmpLockRegistryExclusive();
    02118
    02119     //
    02120     // Make sure the cell passed in is the root cell of the hive.
    02121     //
    02122     if (Cell != Hive->BaseBlock->RootCell) {
    02123         CmpUnlockRegistry();
    02124         return(STATUS_INVALID_PARAMETER);
    02125     }
    02126
    02127     //
    02128     // Make sure there are no open references to key control blocks
    02129     // for this hive.  If there are none, then we can unload the hive.
    02130     //
    02131
    02132     CmHive = CONTAINING_RECORD(Hive, CMHIVE, Hive);
    02133     if ((CmpSearchForOpenSubKeys(Kcb,SearchIfExist) != 0) || (Kcb->RefCount != 1)) {
    02134 #if DBG
    02135         KdPrint(("List of keys open against hive unload was attempted on:\n"));
    02136         CmpSearchKeyControlBlockTree(
    02137             CmpUnloadKeyWorker,
    02138             Hive,
    02139             NULL
    02140             );
    02141 #endif
    02142         CmpUnlockRegistry();
    02143         return(STATUS_CANNOT_DELETE);
    02144     }
    02145
    02146     //
    02147     // Flush any dirty data to disk. If this fails, too bad.
    02148     //
    02149     Command.Command = REG_CMD_FLUSH_KEY;
    02150     Command.Hive = Hive;
    02151     Command.Cell = Cell;
    02152     CmpWorker(&Command);
    02153
    02154     //
    02155     // Remove the hive from the HiveFileList
    02156     //
    02157     Command.Command = REG_CMD_REMOVE_HIVE_LIST;
    02158     Command.CmHive = (PCMHIVE)Hive;
    02159     CmpWorker(&Command);
    02160
    02161     //
    02162     // Unlink from master hive, remove from list
    02163     //
    02164     Success = CmpDestroyHive(Hive, Cell);
    02165
    02166     CmpUnlockRegistry();
    02167
    02168     if (Success) {
    02169         HvFreeHive(Hive);
    02170
    02171         //
    02172         // Close the hive files
    02173         //
    02174         Command.Command = REG_CMD_HIVE_CLOSE;
    02175         Command.CmHive = CmHive;
    02176         CmpWorker(&Command);
    02177
    02178         //
    02179         // free the cm level structure
    02180         //
    02181         ASSERT( CmHive->HiveLock );
    02182         ExFreePool(CmHive->HiveLock);
    02183         CmpFree(CmHive, sizeof(CMHIVE));
    02184
    02185         return(STATUS_SUCCESS);
    02186     } else {
    02187         return(STATUS_INSUFFICIENT_RESOURCES);
    02188     }
    02189
    02190 }

## Variable Documentation

ULONG CmpCacheOnFlag

| Definition at line 220 of file cmp.h. Referenced by CmpAddInfoAfterParseFailure().

PCM_KEY_HASH* CmpCacheTable

| Definition at line 1982 of file cmp.h. Referenced by CmpCacheLookup(), CmpGetSymbolicLink(), CmpInitializeCache(), CmpInsertKeyHash(), CmpRemoveKeyHash(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

ULONG CmpHashTableSize

| Definition at line 1981 of file cmp.h. Referenced by CmpGetSymbolicLink(), CmpInitializeCache(), CmpInsertKeyHash(), CmpRemoveKeyHash(), CmpSearchForOpenSubKeys(), and CmpSearchKeyControlBlockTree().

FAST_MUTEX CmpKcbLock

| Definition at line 229 of file cmp.h. Referenced by CmInitSystem1().

POBJECT_TYPE CmpKeyObjectType

| Definition at line 463 of file cmp.h.

BOOLEAN CmpLazyFlushPending

| Definition at line 1098 of file cmp.h. Referenced by CmpLazyFlushDpcRoutine(), and CmpLazyFlushWorker().

FAST_MUTEX CmpPostLock

| Definition at line 642 of file cmp.h. Referenced by CmInitSystem1().

ERESOURCE CmpRegistryLock

| Definition at line 1174 of file cmp.h. Referenced by CmInitSystem1(), CmpLockRegistry(), CmpLockRegistryExclusive(), and CmpUnlockRegistry().

PCM_TRACE_NOTIFY_ROUTINE CmpTraceRoutine

| Definition at line 74 of file cmp.h.

UNICODE_STRING CmRegistrySystemCloneName

| Definition at line 409 of file cmp.h. Referenced by CmInitSystem1(), CmpDeleteCloneTree(), and CmpInitializeRegistryNames().

ULONG WmiUsePerfClock

| Definition at line 73 of file cmp.h.