You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
678 lines
19 KiB
678 lines
19 KiB
/*****************************************************************************
|
|
* registry.cpp - registry key object implementation
|
|
*****************************************************************************
|
|
* Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
|
|
*/
|
|
|
|
#include "private.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* Factory.
|
|
*/
|
|
|
|
#pragma code_seg("PAGE")
|
|
|
|
/*****************************************************************************
|
|
* CreateRegistryKey()
|
|
*****************************************************************************
|
|
* Creates a registry key object.
|
|
*/
|
|
NTSTATUS
|
|
CreateRegistryKey
|
|
(
|
|
OUT PUNKNOWN * Unknown,
|
|
IN REFCLSID,
|
|
IN PUNKNOWN UnknownOuter OPTIONAL,
|
|
IN POOL_TYPE PoolType
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(Unknown);
|
|
|
|
_DbgPrintF(DEBUGLVL_LIFETIME,("Creating REGISTRYKEY"));
|
|
|
|
STD_CREATE_BODY
|
|
(
|
|
CRegistryKey,
|
|
Unknown,
|
|
UnknownOuter,
|
|
PoolType
|
|
);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* PcNewRegistryKey()
|
|
*****************************************************************************
|
|
* Creates and initializes a registry key object.
|
|
*/
|
|
PORTCLASSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
PcNewRegistryKey
|
|
(
|
|
OUT PREGISTRYKEY * OutRegistryKey,
|
|
IN PUNKNOWN OuterUnknown OPTIONAL,
|
|
IN ULONG RegistryKeyType,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN PVOID DeviceObject OPTIONAL,
|
|
IN PVOID SubDevice OPTIONAL,
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
IN ULONG CreateOptions OPTIONAL,
|
|
OUT PULONG Disposition OPTIONAL
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(OutRegistryKey);
|
|
|
|
//
|
|
// Validate Parameters.
|
|
//
|
|
if (NULL == OutRegistryKey)
|
|
{
|
|
_DbgPrintF(DEBUGLVL_TERSE, ("PcNewRegistryKey : Invalid Parameter."));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
PUNKNOWN unknown;
|
|
NTSTATUS ntStatus =
|
|
CreateRegistryKey
|
|
(
|
|
&unknown,
|
|
GUID_NULL,
|
|
OuterUnknown,
|
|
PagedPool
|
|
);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
PREGISTRYKEYINIT RegistryKey;
|
|
ntStatus =
|
|
unknown->QueryInterface
|
|
(
|
|
IID_IRegistryKey,
|
|
(PVOID *) &RegistryKey
|
|
);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus = RegistryKey->Init( RegistryKeyType,
|
|
DesiredAccess,
|
|
PDEVICE_OBJECT(DeviceObject),
|
|
PSUBDEVICE(SubDevice),
|
|
ObjectAttributes,
|
|
CreateOptions,
|
|
Disposition );
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
*OutRegistryKey = RegistryKey;
|
|
} else
|
|
{
|
|
RegistryKey->Release();
|
|
}
|
|
}
|
|
|
|
unknown->Release();
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Member functions.
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::~CRegistryKey()
|
|
*****************************************************************************
|
|
* Destructor.
|
|
*/
|
|
CRegistryKey::
|
|
~CRegistryKey
|
|
( void
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
_DbgPrintF(DEBUGLVL_LIFETIME,("Destroying REGISTRYKEY (0x%08x)",this));
|
|
|
|
if ( FALSE == m_KeyDeleted )
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ZwClose(m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::NonDelegatingQueryInterface()
|
|
*****************************************************************************
|
|
* Obtains an interface.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
NonDelegatingQueryInterface
|
|
(
|
|
REFIID Interface,
|
|
PVOID * Object
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(Object);
|
|
|
|
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
|
|
{
|
|
*Object = PVOID(PUNKNOWN(this));
|
|
}
|
|
else
|
|
if (IsEqualGUIDAligned(Interface,IID_IRegistryKey))
|
|
{
|
|
*Object = PVOID(PREGISTRYKEYINIT(this));
|
|
}
|
|
else
|
|
{
|
|
*Object = NULL;
|
|
}
|
|
|
|
if (*Object)
|
|
{
|
|
PUNKNOWN(*Object)->AddRef();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::Init()
|
|
*****************************************************************************
|
|
* Initializes a registry key object.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
Init
|
|
(
|
|
IN ULONG RegistryKeyType,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|
IN PSUBDEVICE SubDevice OPTIONAL,
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
IN ULONG CreateOptions OPTIONAL,
|
|
OUT PULONG Disposition OPTIONAL
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
_DbgPrintF(DEBUGLVL_LIFETIME,("Initializing REGISTRYKEY (0x%08x)",this));
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
m_KeyDeleted = TRUE;
|
|
m_GeneralKey = FALSE;
|
|
m_KeyHandle = NULL;
|
|
|
|
switch(RegistryKeyType)
|
|
{
|
|
case GeneralRegistryKey:
|
|
ASSERT(ObjectAttributes);
|
|
|
|
ntStatus = ZwCreateKey( &m_KeyHandle,
|
|
DesiredAccess,
|
|
ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
CreateOptions,
|
|
Disposition );
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
m_GeneralKey = TRUE;
|
|
m_KeyDeleted = FALSE;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
break;
|
|
|
|
case DeviceRegistryKey:
|
|
case DriverRegistryKey:
|
|
case HwProfileRegistryKey:
|
|
{
|
|
ASSERT(DeviceObject);
|
|
|
|
ULONG DevInstKeyType;
|
|
|
|
if (RegistryKeyType == DeviceRegistryKey)
|
|
{
|
|
DevInstKeyType = PLUGPLAY_REGKEY_DEVICE;
|
|
} else if(RegistryKeyType == DriverRegistryKey)
|
|
{
|
|
DevInstKeyType = PLUGPLAY_REGKEY_DRIVER;
|
|
} else
|
|
{
|
|
DevInstKeyType = PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
|
|
}
|
|
|
|
PDEVICE_CONTEXT deviceContext =
|
|
PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
|
|
|
|
PDEVICE_OBJECT PhysicalDeviceObject = deviceContext->PhysicalDeviceObject;
|
|
|
|
ntStatus = IoOpenDeviceRegistryKey( PhysicalDeviceObject,
|
|
DevInstKeyType,
|
|
DesiredAccess,
|
|
&m_KeyHandle );
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
m_GeneralKey = FALSE;
|
|
m_KeyDeleted = FALSE;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DeviceInterfaceRegistryKey:
|
|
{
|
|
ASSERT(DeviceObject);
|
|
ASSERT(SubDevice);
|
|
|
|
ULONG Index = SubdeviceIndex( DeviceObject,
|
|
SubDevice );
|
|
|
|
if(Index != ULONG(-1))
|
|
{
|
|
PDEVICE_CONTEXT deviceContext =
|
|
PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
|
|
|
|
PUNICODE_STRING SymbolicLinkName = &deviceContext->SymbolicLinkNames[Index];
|
|
|
|
ntStatus = IoOpenDeviceInterfaceRegistryKey( SymbolicLinkName,
|
|
DesiredAccess,
|
|
&m_KeyHandle );
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
m_GeneralKey = FALSE;
|
|
m_KeyDeleted = FALSE;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
} else
|
|
{
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
default:
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::QueryKey()
|
|
*****************************************************************************
|
|
* Queries a registry key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
QueryKey
|
|
(
|
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
|
OUT PVOID KeyInformation,
|
|
IN ULONG Length,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwQueryKey( m_KeyHandle,
|
|
KeyInformationClass,
|
|
KeyInformation,
|
|
Length,
|
|
ResultLength );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::EnumerateKey()
|
|
*****************************************************************************
|
|
* Enumerates a registry key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
EnumerateKey
|
|
(
|
|
IN ULONG Index,
|
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
|
OUT PVOID KeyInformation,
|
|
IN ULONG Length,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwEnumerateKey( m_KeyHandle,
|
|
Index,
|
|
KeyInformationClass,
|
|
KeyInformation,
|
|
Length,
|
|
ResultLength );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::QueryValueKey()
|
|
*****************************************************************************
|
|
* Queries a registry value key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
QueryValueKey
|
|
(
|
|
IN PUNICODE_STRING ValueName,
|
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
OUT PVOID KeyValueInformation,
|
|
IN ULONG Length,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwQueryValueKey( m_KeyHandle,
|
|
ValueName,
|
|
KeyValueInformationClass,
|
|
KeyValueInformation,
|
|
Length,
|
|
ResultLength );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::EnumerateValueKey()
|
|
*****************************************************************************
|
|
* Enumerates a registry value key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
EnumerateValueKey
|
|
(
|
|
IN ULONG Index,
|
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
OUT PVOID KeyValueInformation,
|
|
IN ULONG Length,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwEnumerateValueKey( m_KeyHandle,
|
|
Index,
|
|
KeyValueInformationClass,
|
|
KeyValueInformation,
|
|
Length,
|
|
ResultLength );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::SetValueKey()
|
|
*****************************************************************************
|
|
* Sets a registry value key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
SetValueKey
|
|
(
|
|
IN PUNICODE_STRING ValueName OPTIONAL,
|
|
IN ULONG Type,
|
|
IN PVOID Data,
|
|
IN ULONG DataSize
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwSetValueKey( m_KeyHandle,
|
|
ValueName,
|
|
0,
|
|
Type,
|
|
Data,
|
|
DataSize );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::QueryRegistryValues()
|
|
*****************************************************************************
|
|
* Queries several registry values with a single call.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
QueryRegistryValues
|
|
(
|
|
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
|
|
IN PVOID Context OPTIONAL
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(QueryTable);
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_HANDLE,
|
|
PWSTR(m_KeyHandle),
|
|
QueryTable,
|
|
Context,
|
|
NULL );
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::NewSubKey()
|
|
*****************************************************************************
|
|
* Opens/creates a subkey for an open registry key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
NewSubKey
|
|
(
|
|
OUT PREGISTRYKEY * RegistrySubKey,
|
|
IN PUNKNOWN OuterUnknown,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN PUNICODE_STRING SubKeyName,
|
|
IN ULONG CreateOptions,
|
|
OUT PULONG Disposition OPTIONAL
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(RegistrySubKey);
|
|
ASSERT(SubKeyName);
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
ASSERT(m_KeyHandle);
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
SubKeyName,
|
|
OBJ_INHERIT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
|
m_KeyHandle,
|
|
NULL );
|
|
|
|
|
|
return PcNewRegistryKey( RegistrySubKey,
|
|
OuterUnknown,
|
|
GeneralRegistryKey,
|
|
DesiredAccess,
|
|
NULL,
|
|
NULL,
|
|
&ObjectAttributes,
|
|
CreateOptions,
|
|
Disposition );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CRegistryKey::DeleteKey()
|
|
*****************************************************************************
|
|
* Deletes a registry key.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CRegistryKey::
|
|
DeleteKey
|
|
(
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if ( m_KeyDeleted )
|
|
{
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
ASSERT(!m_KeyHandle);
|
|
}
|
|
else if ( FALSE == m_GeneralKey )
|
|
{
|
|
ntStatus = STATUS_ACCESS_DENIED;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_KeyHandle);
|
|
ntStatus = ZwDeleteKey( m_KeyHandle );
|
|
|
|
if(NT_SUCCESS( ntStatus ))
|
|
{
|
|
m_KeyDeleted = TRUE;
|
|
m_KeyHandle = NULL;
|
|
}
|
|
else
|
|
{
|
|
_DbgPrintF(DEBUGLVL_TERSE,("ZwDeleteKey failed for %x!!!",m_KeyHandle));
|
|
}
|
|
}
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* PcGetDeviceProperty()
|
|
*****************************************************************************
|
|
* This wraps a call to IoGetDeviceProperty.
|
|
*/
|
|
PORTCLASSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
PcGetDeviceProperty
|
|
(
|
|
IN PVOID DeviceObject,
|
|
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
|
|
IN ULONG BufferLength,
|
|
OUT PVOID PropertyBuffer,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
PDEVICE_CONTEXT deviceContext =
|
|
PDEVICE_CONTEXT(PDEVICE_OBJECT(DeviceObject)->DeviceExtension);
|
|
|
|
PDEVICE_OBJECT PhysicalDeviceObject = deviceContext->PhysicalDeviceObject;
|
|
|
|
return IoGetDeviceProperty( PhysicalDeviceObject,
|
|
DeviceProperty,
|
|
BufferLength,
|
|
PropertyBuffer,
|
|
ResultLength );
|
|
}
|
|
|
|
#pragma code_seg()
|
|
|
|
|
|
|