|
|
/******************************************************************************
* * $RCSfile: DrvReg.cpp $ * $Source: u:/si/VXP/Wdm/Classes/DrvReg.cpp $ * $Author: Max $ * $Date: 1998/09/28 23:22:38 $ * $Revision: 1.5 $ * * Written by: Max Paklin * Purpose: Implementation of registry class * ******************************************************************************* * * Copyright � 1996-98, AuraVision Corporation. All rights reserved. * * AuraVision Corporation makes no warranty of any kind, express or implied, * with regard to this software. In no event shall AuraVision Corporation * be liable for incidental or consequential damages in connection with or * arising from the furnishing, performance, or use of this software. * * Tab step is to be set to 4 to achive the best readability for this code. * *******************************************************************************/
#include "Comwdm.h"
#pragma hdrstop
// Convert GUID to WCHAR (or WCHAR to GUID) string MAX_GUIDLENGTH characters
void CKsRegKey::GuidToWChar( const GUID guid, LPWSTR pwszString ) { UNICODE_STRING usString; usString.Length = 0; usString.MaximumLength = MAX_GUIDLENGTH*sizeof( WCHAR ); usString.Buffer = pwszString; RtlStringFromGUID( guid, &usString ); } NTSTATUS CKsRegKey::WCharToGuid( LPCWSTR pwszString, GUID guid ) { UNICODE_STRING usString; usString.Length = (wcslen( pwszString )+1)*sizeof( WCHAR ); usString.MaximumLength = MAX_GUIDLENGTH*sizeof( WCHAR ); usString.Buffer = (PWSTR)pwszString; return RtlGUIDFromString( &usString, &guid ); }
// Constructor helper function
void CKsRegKey::Create( LPCWSTR pwszKey, LPCWSTR pwszSubKey, PVOID hHandle, PDEVICE_OBJECT pDeviceObject ) { int nLength;
// Calculating the length of key
if( pwszKey ) nLength = wcslen( pwszKey )+1; else nLength = 0; if( pwszSubKey ) nLength += wcslen( pwszSubKey )+1;
if( nLength > 0 ) { // Allocating memory for key
m_pwszKey = (PWCHAR)ExAllocatePool( PagedPool, nLength*sizeof( WCHAR ) ); if( m_pwszKey == NULL ) { DebugPrint(( DebugLevelFatal, "%s: out of memory\n", __FILE__ )); DEBUG_BREAKPOINT(); } else { if( pwszKey ) wcscpy( m_pwszKey, pwszKey ); else wcscpy( m_pwszKey, L"" ); if( pwszSubKey ) wcscat( m_pwszKey, pwszSubKey ); } } else m_pwszKey = NULL;
m_hHandle = hHandle; m_pDeviceObject = pDeviceObject; }
// Helper function that is used to get currently used registry path to get/set values.
// Returned values are used as a parameters to RtlQueryRegistryValues/RtlWriteRegistryValues.
// The first parameter is flag (first parameter) to abovementioned Windows' registry
// functions. It can be or RTL_REGISTRY_HANDLE or RTL_REGISTRY_ABSOLUTE. The first one means
// that return value of this function is actually handle of registry key, while the second
// tells caller that return value is absolute registry key string. The last parameter is
// used to store registry key to close if it was temporary opened
PWSTR CKsRegKey::GetInputData( PULONG puRelativeTo, PHANDLE phHandleToDelete, ACCESS_MASK amDesiredAccess, BOOL bCreateHandle ) { *phHandleToDelete = NULL; PWSTR pKey = NULL; NTSTATUS ntStatus;
if( m_hHandle || bCreateHandle ) { // We have handle to key to work with. Open specified subkey and return it telling
// that it is handle and that subkey should be closed when it is not needed
*puRelativeTo = RTL_REGISTRY_HANDLE; if( m_pwszKey && wcslen( m_pwszKey ) > 0 ) { HANDLE hHandle; OBJECT_ATTRIBUTES objAttr; UNICODE_STRING usValue;
RtlInitUnicodeString( &usValue, m_pwszKey ); InitializeObjectAttributes( &objAttr, &usValue, OBJ_CASE_INSENSITIVE, m_hHandle, NULL ); if( (ntStatus = ZwOpenKey( &hHandle, amDesiredAccess, &objAttr )) == STATUS_SUCCESS ) { // Subkey was successfully opened, so mark it as "to be released when
// it is not needed anymore"
*phHandleToDelete = hHandle; pKey = (PWSTR)hHandle; } else DebugPrint(( DebugLevelWarning, "ZwOpenKey() failed: 0x%X\n", ntStatus )); } else pKey = (PWSTR)m_hHandle; } else if( m_pDeviceObject ) { // We have handle to driver key and we are going to work with data store under it.
// Open specified subkey and return it telling that it is handle and that subkey
// should be closed when it is not needed
*puRelativeTo = RTL_REGISTRY_HANDLE; // First open key for our device object
ntStatus = IoOpenDeviceRegistryKey( (PDEVICE_OBJECT)m_pDeviceObject, PLUGPLAY_REGKEY_DRIVER, amDesiredAccess, phHandleToDelete ); if( ntStatus == STATUS_SUCCESS ) { if( m_pwszKey && wcslen( m_pwszKey ) > 0 ) { // Subkey specified. So open it and mark it as "to be released when
// it is not needed anymore"
HANDLE hHandle = NULL; OBJECT_ATTRIBUTES objAttr; UNICODE_STRING usValue;
RtlInitUnicodeString( &usValue, m_pwszKey ); InitializeObjectAttributes( &objAttr, &usValue, OBJ_CASE_INSENSITIVE, *phHandleToDelete, NULL ); if( ZwOpenKey( &hHandle, amDesiredAccess, &objAttr ) == STATUS_SUCCESS ) pKey = (PWSTR)hHandle; ZwClose( *phHandleToDelete ); *phHandleToDelete = hHandle; } else pKey = (PWSTR)(*phHandleToDelete); } else DebugPrint(( DebugLevelWarning, "IoOpenDeviceRegistryKey() failed: 0x%X\n", ntStatus )); } else if( m_pwszKey ) { // We have registry key object created as an absolute path to registry key
*puRelativeTo = RTL_REGISTRY_ABSOLUTE; pKey = m_pwszKey; }
return pKey; }
// Set textual and integer values to registry key
BOOL CKsRegKey::SetValue( LPCWSTR pwszValue, LPCWSTR pwszSetTo ) { if( IsKey() ) { ULONG uRelativeTo; HANDLE hHandleToDelete; PWSTR pKey = GetInputData( &uRelativeTo, &hHandleToDelete, KEY_WRITE ); if( pKey ) { NTSTATUS ntStatus = RtlWriteRegistryValue( uRelativeTo, pKey, pwszValue, REG_SZ, (PVOID)pwszSetTo, (wcslen( pwszSetTo )+1)*sizeof( WCHAR ) ); // Close key after the information is read and the key is not needed anymore
if( hHandleToDelete ) { ZwClose( hHandleToDelete ); } #ifdef DEBUG
if( ntStatus != STATUS_SUCCESS ) { DebugPrint(( DebugLevelWarning, "RtlWriteRegistryValue() failed: 0x%X\n", ntStatus )); } #endif // DEBUG
return (BOOL)(ntStatus == STATUS_SUCCESS); } }
return FALSE; } BOOL CKsRegKey::SetValue( LPCWSTR pwszValue, int nSetTo ) { if( IsKey() ) { ULONG uRelativeTo; HANDLE hHandleToDelete; PWSTR pKey = GetInputData( &uRelativeTo, &hHandleToDelete, KEY_WRITE ); if( pKey ) { DWORD dwSetTo = (DWORD)nSetTo; NTSTATUS ntStatus = RtlWriteRegistryValue( uRelativeTo, pKey, pwszValue, REG_DWORD, &dwSetTo, sizeof( dwSetTo ) ); // Close key after the information is read and the key is not needed anymore
if( hHandleToDelete ) { ZwClose( hHandleToDelete ); } #ifdef DEBUG
if( ntStatus != STATUS_SUCCESS ) { DebugPrint(( DebugLevelWarning, "RtlWriteRegistryValue() failed: 0x%X\n", ntStatus )); } #endif // DEBUG
return (BOOL)(ntStatus == STATUS_SUCCESS); } }
return FALSE; }
// Get string and integer value from key. We use this a little bit ugly technique because
// it is the easiest way to do what we want to do. The optimal way would be to put all the
// nessessary data to a number of RTL_QUERY_REGISTRY_TABLE tables and read all of them
// at once but it would be inconvinient for user of this class
BOOL CKsRegKey::GetValue( LPCWSTR pwszGetFrom, LPWSTR pwszValue, USHORT ushSize, LPCWSTR pwszDefault ) { BOOL bResult = FALSE;
if( IsKey() ) { ULONG uRelativeTo; HANDLE hHandleToDelete; PWSTR pKey = GetInputData( &uRelativeTo, &hHandleToDelete, KEY_READ ); if( pKey ) { RTL_QUERY_REGISTRY_TABLE qTable[2]; UNICODE_STRING usValue, usDefault; NTSTATUS ntStatus;
// Prepare UNICODE strings for buffer to put data into and for default value
usValue.Length = 0; usValue.MaximumLength = ushSize; usValue.Buffer = pwszValue; RtlInitUnicodeString( &usDefault, pwszDefault );
RtlZeroMemory( qTable, sizeof( qTable ) ); qTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; qTable[0].Name = (PWSTR)pwszGetFrom; qTable[0].EntryContext = &usValue; qTable[0].DefaultType = REG_SZ; qTable[0].DefaultData = &usDefault; qTable[0].DefaultLength = 0;
ntStatus = RtlQueryRegistryValues( uRelativeTo, pKey, qTable, NULL, NULL ); if( ntStatus == STATUS_SUCCESS ) bResult = TRUE; else DebugPrint(( DebugLevelWarning, "RtlQueryRegistryValues() failed: 0x%X\n", ntStatus )); // Close key after the information is read and the key is not needed anymore
if( hHandleToDelete ) ZwClose( hHandleToDelete ); } }
return bResult; } BOOL CKsRegKey::GetValue( LPCWSTR pwszGetFrom, PDWORD pdwValue, ULONG ulSize ) { BOOL bResult = FALSE;
if( IsKey() ) { ULONG uRelativeTo; HANDLE hHandleToDelete; PWSTR pKey = GetInputData( &uRelativeTo, &hHandleToDelete, KEY_READ, TRUE ); if( pKey ) { ULONG ulReadSize; UNICODE_STRING usName; // Here we will be using the nasty trick. Use user's buffer not only for data that
// user requested but also for storing KEY_VALUE_PARTIAL_INFORMATION structure.
// ZwQueryValueKey() will fill out KEY_VALUE_PARTIAL_INFORMATION structure that
// will contain real data at the end of it. All that we have to do is to move the
// tail with data to the beginning of the user's buffer. Of course, it introduces
// potential danger when, for example, user provides buffer of size of 20 bytes for
// reading the data that is 15 bytes long. In this example only a few bytes of
// registry data will be read. However it is not as ugly as it could seem at a first
// glance because in this case we will return FALSE to the user to signal that the
// buffer size is probably not enough for storing the data ('ulSize > ulReadSize'
// check will do it). Therefore the size of buffer should be greater or equal to
// RealSizeOfRegistryData+sizeof( KEY_VALUE_PARTIAL_INFORMATION )-
// sizeof( KEY_VALUE_PARTIAL_INFORMATION.Data )+1
ASSERT( ulSize > sizeof( KEY_VALUE_PARTIAL_INFORMATION ) ); PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)pdwValue;
ASSERT( hHandleToDelete ); RtlInitUnicodeString( &usName, pwszGetFrom ); NTSTATUS ntStatus = ZwQueryValueKey( (HANDLE)pKey, &usName, KeyValuePartialInformation, pKeyInfo, ulSize, &ulReadSize ); if( ntStatus != STATUS_SUCCESS ) DebugPrint(( DebugLevelWarning, "ZwQueryValueKey() failed: 0x%X\n", ntStatus )); else if( ulSize > ulReadSize ) { // We succeeded only if the read size is less than the size of our buffer.
// Otherwise the size of data in registry could be bigger than supplied buffer
bResult = TRUE;
// Move the actual data at the beginning of user's buffer
ASSERT( pKeyInfo->Type == REG_BINARY ); ULONG ulDataLength = pKeyInfo->DataLength; PBYTE pbData = (PBYTE)&pKeyInfo->Data, pbValue = (PBYTE)pdwValue; for( ULONG i = 0; i < ulDataLength; i++, pbData++, pbValue++ ) *pbValue = *pbData; #ifdef _DEBUG
for( ; i < ulSize; i++, pbValue++ ) *pbValue = 0; #endif
} // Close key after the information is read and the key is not needed anymore
if( hHandleToDelete ) ZwClose( hHandleToDelete ); } }
return bResult; } BOOL CKsRegKey::GetValue( LPCWSTR pwszGetFrom, long& lValue, long lDefault ) { BOOL bResult = FALSE;
if( IsKey() ) { ULONG uRelativeTo; HANDLE hHandleToDelete; PWSTR pKey = GetInputData( &uRelativeTo, &hHandleToDelete, KEY_READ ); if( pKey ) { RTL_QUERY_REGISTRY_TABLE qTable[2]; DWORD dwData = 0; NTSTATUS ntStatus;
RtlZeroMemory( qTable, sizeof( qTable ) ); qTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; qTable[0].Name = (PWSTR)pwszGetFrom; qTable[0].EntryContext = &dwData; qTable[0].DefaultType = REG_DWORD; qTable[0].DefaultData = &lDefault; qTable[0].DefaultLength = sizeof( lDefault );
ntStatus = RtlQueryRegistryValues( uRelativeTo, pKey, qTable, NULL, NULL ); if( ntStatus == STATUS_SUCCESS ) { lValue = (int)dwData; bResult = TRUE; } else DebugPrint(( DebugLevelWarning, "RtlQueryRegistryValues() failed: 0x%X\n", ntStatus )); // Close key after the information is read and the key is not needed anymore
if( hHandleToDelete ) ZwClose( hHandleToDelete ); } }
return bResult; }
// Delete registry subkey
void DeleteSubKey( LPWSTR pwszKey, LPCWSTR pwszSubKey ) { if( pwszKey ) { HANDLE hHandle; OBJECT_ATTRIBUTES objAttr; UNICODE_STRING usKey;
RtlInitUnicodeString( &usKey, pwszKey ); RtlZeroMemory( &objAttr, sizeof( objAttr ) ); objAttr.Length = sizeof( objAttr ); objAttr.ObjectName = &usKey; NTSTATUS ntStatus = ZwOpenKey( &hHandle, KEY_SET_VALUE | KEY_CREATE_SUB_KEY, &objAttr ); if( ntStatus == STATUS_SUCCESS ) { ntStatus = ZwDeleteKey( hHandle ); ASSERT( ntStatus == STATUS_SUCCESS ); } else DebugPrint(( DebugLevelWarning, "ZwOpenKey() failed: 0x%X\n", ntStatus )); } }
|