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.

ZwQueryKey

Itérer à travers les sous-clés de la clé, en examinant les propriétés de chacune d’elles.

ZwEnumerateKey

Examinez les propriétés d’une valeur de clé, y compris les données de la valeur.

ZwQueryValueKey

Itérer à travers les valeurs d’une clé, en examinant les propriétés de chacune d’elles.

ZwEnumerateValueKey

Définissez les données pour une valeur associée à une clé.

ZwSetValueKey

Supprime une clé.

ZwDeleteKey

Supprimez une valeur de clé.

ZwDeleteValueKey

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.