Utilisation d’un handle pour un objet Registry-Key
Le tableau suivant répertorie les opérations que les pilotes peuvent effectuer sur une clé ouverte, ainsi que les routines appropriées à appeler.
Opération | Routine à appeler |
---|---|
Examinez les propriétés de la clé, telles que son nom ou le nombre de ses sous-clés. |
|
Itérer à travers les sous-clés de la clé, en examinant les propriétés de chacune d’elles. |
|
Examinez les propriétés d’une valeur de clé, y compris les données de la valeur. |
|
Itérer à travers les valeurs d’une clé, en examinant les propriétés de chacune d’elles. |
|
Définissez les données pour une valeur associée à une clé. |
|
Supprime une clé. |
|
Supprimez une valeur de clé. |
Une fois que le pilote a terminé ses manipulations, il doit appeler ZwClose pour fermer la poignée, même s’il a déjà appelé ZwDeleteKey pour supprimer la clé. (Une fois qu’une clé est supprimée, toutes les poignées ouvertes à celle-ci deviennent non valides, mais le pilote doit toujours fermer le handle.)
L’exemple de code suivant montre comment ouvrir un handle pour une clé nommée \Registry\Machine\Software\MyApp\, puis récupérer des données de clé et fermer le handle.
//
// 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);
}
Le système met en cache les modifications clés dans la mémoire et les écrit sur le disque toutes les quelques secondes. Pour forcer une modification de clé sur le disque, appelez ZwFlushKey.
Pour manipuler le Registre via une interface plus simple, les pilotes peuvent également appeler les routines RtlXxxRegistryXxx . Pour plus d’informations, consultez Routines de la bibliothèque Run-Time registre.