Usar un identificador para un objeto Registry-Key
En la tabla siguiente se enumeran las operaciones que los controladores pueden realizar en una clave abierta, así como las rutinas adecuadas que se deben llamar.
Operación | Rutina a la que llamar |
---|---|
Examine las propiedades de la clave, como su nombre o el número de sus subclaves. |
|
Recorra en iteración las subclaves de la clave y examine las propiedades de cada una. |
|
Examine las propiedades de un valor de clave, incluidos los datos del valor. |
|
Recorra en iteración los valores de una clave y examine las propiedades de cada una. |
|
Establezca los datos de un valor asociado a una clave. |
|
Elimina una clave. |
|
Elimine un valor de clave. |
Una vez que el controlador haya terminado sus manipulaciones, debe llamar a ZwClose para cerrar el identificador, incluso si ya ha llamado ZwDeleteKey para eliminar la clave. (Una vez eliminada una clave, todos los identificadores abiertos se convierten en no válidos, pero el controlador todavía debe cerrar el identificador).
En el ejemplo de código siguiente se muestra cómo abrir un identificador para una clave denominada \Registry\Machine\Software\MyCompany\MyApp y, a continuación, recuperar los datos de clave y cerrar el identificador.
//
// Get the frame location from the registry key
// HKLM\SOFTWARE\MyCompany\MyApp.
// For example: "FrameLocation"="X:\\MyApp\\Frames"
//
HANDLE handleRegKey = NULL;
for (int n = 0; n < 1; n++)
{
NTSTATUS status = NULL;
UNICODE_STRING RegistryKeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&RegistryKeyName, L"\\Registry\\Machine\\Software\\MyCompany\\MyApp");
InitializeObjectAttributes(&ObjectAttributes,
&RegistryKeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, // handle
NULL);
status = ZwOpenKey(&handleRegKey, KEY_READ, &ObjectAttributes);
// If the driver cannot open the key, the driver cannot continue.
// In this situation, the driver was probably set up incorrectly
// and worst case, the driver cannot stream.
if( NT_SUCCESS(status) == FALSE )
{
break;
}
// The driver obtained the registry key.
PKEY_VALUE_FULL_INFORMATION pKeyInfo = NULL;
UNICODE_STRING ValueName;
ULONG ulKeyInfoSize = 0;
ULONG ulKeyInfoSizeNeeded = 0;
// The driver requires the following value.
RtlInitUnicodeString(&ValueName, L"FrameLocation");
// Determine the required size of keyInfo.
status = ZwQueryValueKey( handleRegKey,
&ValueName,
KeyValueFullInformation,
pKeyInfo,
ulKeyInfoSize,
&ulKeyInfoSizeNeeded );
// The driver expects one of the following errors.
if( (status == STATUS_BUFFER_TOO_SMALL) || (status == STATUS_BUFFER_OVERFLOW) )
{
// Allocate the memory required for the key.
ulKeyInfoSize = ulKeyInfoSizeNeeded;
pKeyInfo = (PKEY_VALUE_FULL_INFORMATION) ExAllocatePoolWithTag( NonPagedPool, ulKeyInfoSizeNeeded, g_ulTag);
if( NULL == pKeyInfo )
{
break;
}
RtlZeroMemory( pKeyInfo, ulKeyInfoSize );
// Get the key data.
status = ZwQueryValueKey( handleRegKey,
&ValueName,
KeyValueFullInformation,
pKeyInfo,
ulKeyInfoSize,
&ulKeyInfoSizeNeeded );
if( (status != STATUS_SUCCESS) || (ulKeyInfoSizeNeeded != ulKeyInfoSize) || (NULL == pKeyInfo) )
{
break;
}
// Fill in the frame location if it has not been filled in already.
if ( NULL == m_szwFramePath )
{
m_ulFramePathLength = pKeyInfo->DataLength;
ULONG_PTR pSrc = NULL;
pSrc = (ULONG_PTR) ( (PBYTE) pKeyInfo + pKeyInfo->DataOffset);
m_szwFramePath = (LPWSTR) ExAllocatePoolWithTag( NonPagedPool, m_ulFramePathLength, g_ulTag);
if ( NULL == m_szwFramePath )
{
m_ulFramePathLength = 0;
break;
}
// Copy the frame path.
RtlCopyMemory(m_szwFramePath, (PVOID) pSrc, m_ulFramePathLength);
}
// The driver is done with the pKeyInfo.
xFreePoolWithTag(pKeyInfo, g_ulTag);
} // if( (status == STATUS_BUFFER_TOO_SMALL) || (status == STATUS_BUFFER_OVERFLOW) )
} // Get the Frame location from the registry key.
// All done with the registry.
if (NULL != handleRegKey)
{
ZwClose(handleRegKey);
}
El sistema almacena en caché los cambios de clave en la memoria y los escribe en el disco cada pocos segundos. Para forzar un cambio de clave en el disco, llame a ZwFlushKey.
Para manipular el registro a través de una interfaz más sencilla, los controladores también pueden llamar a las rutinas RtlXxxRegistryXxx . Para obtener más información, vea Rutinas de biblioteca de Run-Time del Registro.