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_NODEPBOOT_DRIVER_NODE
typedef _CM_KEY_BODY CM_KEY_BODY
typedef _CM_KEY_BODYPCM_KEY_BODY
typedef _CM_POST_KEY_BODY CM_POST_KEY_BODY
typedef _CM_POST_KEY_BODYPCM_POST_KEY_BODY
typedef _CM_NOTIFY_BLOCK CM_NOTIFY_BLOCK
typedef _CM_NOTIFY_BLOCKPCM_NOTIFY_BLOCK
typedef enum _POST_BLOCK_TYPE POST_BLOCK_TYPE
typedef _CM_SYNC_POST_BLOCK CM_SYNC_POST_BLOCK
typedef _CM_SYNC_POST_BLOCKPCM_SYNC_POST_BLOCK
typedef _CM_ASYNC_USER_POST_BLOCK CM_ASYNC_USER_POST_BLOCK
typedef _CM_ASYNC_USER_POST_BLOCKPCM_ASYNC_USER_POST_BLOCK
typedef _CM_ASYNC_KERNEL_POST_BLOCK CM_ASYNC_KERNEL_POST_BLOCK
typedef _CM_ASYNC_KERNEL_POST_BLOCKPCM_ASYNC_KERNEL_POST_BLOCK
typedef _CM_POST_BLOCK_UNION CM_POST_BLOCK_UNION
typedef _CM_POST_BLOCK_UNIONPCM_POST_BLOCK_UNION
typedef _CM_POST_BLOCK CM_POST_BLOCK
typedef _CM_POST_BLOCKPCM_POST_BLOCK
typedef _CMHIVE CMHIVE
typedef _CMHIVEPCMHIVE
typedef _REGISTRY_COMMAND REGISTRY_COMMAND
typedef _REGISTRY_COMMANDPREGISTRY_COMMAND
typedef _CM_PARSE_CONTEXT CM_PARSE_CONTEXT
typedef _CM_PARSE_CONTEXTPCM_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_ENTRYPHIVE_LIST_ENTRY
typedef _CM_HARDWARE_PROFILE CM_HARDWARE_PROFILE
typedef _CM_HARDWARE_PROFILEPCM_HARDWARE_PROFILE
typedef _CM_HARDWARE_PROFILE_LIST CM_HARDWARE_PROFILE_LIST
typedef _CM_HARDWARE_PROFILE_LISTPCM_HARDWARE_PROFILE_LIST
typedef _CM_HARDWARE_PROFILE_ALIAS CM_HARDWARE_PROFILE_ALIAS
typedef _CM_HARDWARE_PROFILE_ALIASPCM_HARDWARE_PROFILE_ALIAS
typedef _CM_HARDWARE_PROFILE_ALIAS_LIST CM_HARDWARE_PROFILE_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ALIAS_LISTPCM_HARDWARE_PROFILE_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS CM_HARDWARE_PROFILE_ACPI_ALIAS
typedef _CM_HARDWARE_PROFILE_ACPI_ALIASPCM_HARDWARE_PROFILE_ACPI_ALIAS
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST
typedef _CM_HARDWARE_PROFILE_ACPI_ALIAS_LISTPCM_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_HASHCmpCacheTable


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  )     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  )     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  )     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  )     CmpAllocatePostBlock(b,REG_NOTIFY_MASTER_POST,NULL,NULL)
 

Definition at line 1471 of file cmp.h.

Referenced by NtNotifyChangeMultipleKeys().

#define CmpAllocateSlavePostBlock b,
k,
 )     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)->Flink = (a)->Blink = NULL
 

Definition at line 54 of file cmp.h.

Referenced by CmNotifyRunDown(), CmpFlushNotify(), CmpFreePostBlock(), and CmpPostNotify().

#define CmpCopyTree s,
c,
t,
 )     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,
 )     CmpCopySyncTree(s,c,t,l,f,Copy)
 

Definition at line 1327 of file cmp.h.

Referenced by CmpSaveBootControlSet().

#define CmpDumpSecurityDescriptor x,
 ) 
 

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  ) 
 

Definition at line 142 of file cmp.h.

Referenced by CmpGetValueDataFromCache(), CmpGetValueKeyFromCache(), and CmpGetValueListFromCache().

#define CmpMakeSpecialPoolReadWrite  ) 
 

Definition at line 143 of file cmp.h.

Referenced by CmpCleanUpKcbValueCache(), CmpGetValueDataFromCache(), and CmpGetValueKeyFromCache().

#define CmpMakeValueCacheReadOnly a,
 ) 
 

Definition at line 144 of file cmp.h.

Referenced by CmEnumerateValueKey(), and CmQueryValueKey().

#define CmpMakeValueCacheReadWrite a,
 ) 
 

Definition at line 145 of file cmp.h.

Referenced by CmEnumerateValueKey(), and CmQueryValueKey().

#define CmpMarkAllBinsReadOnly  ) 
 

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

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

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

Definition at line 170 of file cmp.h.

#define HvpMarkBinReadWrite a,
 ) 
 

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.


Generated on Sat May 15 19:43:10 2004 for test by doxygen 1.3.7