Registry-Key 개체에 핸들 사용
다음 표에서는 드라이버가 열려 있는 키에서 수행할 수 있는 작업과 호출할 적절한 루틴을 나열합니다.
작업 | 호출할 루틴 |
---|---|
키의 이름 또는 하위 키 수와 같은 키의 속성을 검사합니다. |
|
키의 하위 키를 반복하여 각 키의 속성을 검사합니다. |
|
값의 데이터를 포함하여 키 값의 속성을 검사합니다. |
|
키의 값을 반복하여 각 키의 속성을 검사합니다. |
|
키와 연결된 값에 대한 데이터를 설정합니다. |
|
키를 삭제합니다. |
|
키 값을 삭제합니다. |
드라이버가 조작을 완료한 후에는 ZwClose 를 호출하여 키를 삭제하기 위해 ZwDeleteKey 를 이미 호출한 경우에도 핸들을 닫아야 합니다. 키가 삭제되면 키가 열려 있는 모든 핸들이 유효하지 않지만 드라이버는 핸들을 닫아야 합니다.
다음 코드 예제에서는 \Registry\Machine\Software\MyCompany\MyApp이라는 키에 대한 핸들을 연 다음 키 데이터를 검색하고 핸들을 닫는 방법을 보여 줍니다.
//
// 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);
}
시스템은 메모리의 키 변경 내용을 캐시하고 몇 초마다 디스크에 씁니다. 키를 강제로 디스크로 변경하려면 ZwFlushKey를 호출합니다.
더 간단한 인터페이스를 통해 레지스트리를 조작하기 위해 드라이버는 RtlXxx레지스트리Xxx 루틴을 호출할 수도 있습니다. 자세한 내용은 레지스트리 Run-Time 라이브러리 루틴을 참조하세요.