Uso di un handle per un oggetto Registry-Key
Nella tabella seguente sono elencate le operazioni che i driver possono eseguire su una chiave aperta e sulle routine appropriate da chiamare.
Operazione | Routine da chiamare |
---|---|
Esaminare le proprietà della chiave, ad esempio il nome o il numero di sottochiave. |
|
Eseguire l'iterazione delle sottochiave della chiave, esaminando le proprietà di ognuno di essi. |
|
Esaminare le proprietà di un valore chiave, inclusi i dati del valore. |
|
Eseguire l'iterazione dei valori di una chiave, esaminando le proprietà di ognuno di essi. |
|
Impostare i dati per un valore associato a una chiave. |
|
Eliminare una chiave. |
|
Eliminare un valore di chiave. |
Al termine delle modifiche, il driver deve chiamare ZwClose per chiudere l'handle, anche se ha già chiamato ZwDeleteKey per eliminare la chiave. Una volta eliminata una chiave, tutti gli handle aperti per diventano non validi, tuttavia il driver deve comunque chiudere l'handle.
Nell'esempio di codice seguente viene illustrato come aprire un handle per una chiave denominata \Registry\Machine\Software\MyCompany\MyApp, quindi recuperare i dati delle chiavi e chiudere l'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);
}
Il sistema memorizza nella cache le modifiche della chiave nella memoria e li scrive su disco ogni pochi secondi. Per forzare una modifica della chiave su disco, chiamare ZwFlushKey.
Per modificare il Registro di sistema tramite un'interfaccia più semplice, i driver possono anche chiamare le routine RtlXxxRegistroXxx . Per altre informazioni, vedere Routine di libreria Run-Time Registro di sistema.