|
|
/*==========================================================================
* * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: creg.cpp * Content: * This module contains the implementation of the CRegistry class. * For a class description, see creg.h * * History: * Date By Reason * ==== == ====== * 07/16/99 rodtoll Created * 08/18/99 rodtoll Added Register/UnRegister that can be used to * allow COM objects to register themselves. * 08/25/99 rodtoll Updated to provide read/write of binary (blob) data * 10/05/99 rodtoll Added DPF_MODNAMEs * 10/07/99 rodtoll Updated to work in Unicode * 10/08/99 rodtoll Fixes to DeleteKey / Reg/UnReg for Win9X * 10/15/99 rodtoll Plugged some memory leaks * 10/27/99 pnewson added Open() call that takes a GUID * 01/18/00 mjn Added GetMaxKeyLen function * 01/24/00 mjn Added GetValueSize function * 01/24/00 rodtoll Fixed error handling for ReadString (Unicode version) * 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k on non-admin account * rodtoll Bug #32952 - Does not run on Win95 GOLD w/o IE4 -- modified * to allow reads of REG_BINARY when expecting REG_DWORD * 05/02/00 mjn Changed CRegistry::Open() to use KEY_READ when Create set to FALSE * 06/08/00 rmt Updated to use common string utils * 07/06/00 rmt Modified to allow seperate read/write parameter * 07/09/2000 rodtoll Added signature bytes * 07/21/00 rmt Fixed a memory leak * 08/08/2000 rmt Bug #41736 - AV in call to lstrcpy by COM_GetDllName * 08/28/2000 masonb Voice Merge: Modified platform checks to use osind.cpp layer * 08/30/2000 rodtoll Bug #171822 - PREFIX Bug * 04/13/2001 VanceO Moved granting registry permissions into common, and * added DeleteValue and EnumValues. * 06/19/2001 RichGr DX8.0 added special security rights for "everyone" - remove them if * they exist with new RemoveAllAccessSecurityPermissions() method. ***************************************************************************/
#include "dncmni.h"
#ifndef DPNBUILD_NOREGISTRY
#ifdef WINNT
// Security function prototypes
typedef BOOL (*PALLOCATEANDINITIALIZESID)( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, // authority
BYTE nSubAuthorityCount, // count of subauthorities
DWORD dwSubAuthority0, // subauthority 0
DWORD dwSubAuthority1, // subauthority 1
DWORD dwSubAuthority2, // subauthority 2
DWORD dwSubAuthority3, // subauthority 3
DWORD dwSubAuthority4, // subauthority 4
DWORD dwSubAuthority5, // subauthority 5
DWORD dwSubAuthority6, // subauthority 6
DWORD dwSubAuthority7, // subauthority 7
PSID *pSid // SID
);
typedef VOID (*PBUILDTRUSTEEWITHSID)( PTRUSTEE pTrustee, // structure
PSID pSid // trustee name
);
typedef DWORD (*PSETENTRIESINACL)( ULONG cCountOfExplicitEntries, // number of entries
PEXPLICIT_ACCESS pListOfExplicitEntries, // buffer
PACL OldAcl, // original ACL
PACL *NewAcl // new ACL
);
typedef DWORD (*PSETSECURITYINFO)( HANDLE handle, // handle to object
SE_OBJECT_TYPE ObjectType, // object type
SECURITY_INFORMATION SecurityInfo, // buffer
PSID psidOwner, // new owner SID
PSID psidGroup, // new primary group SID
PACL pDacl, // new DACL
PACL pSacl // new SACL
);
typedef PVOID (*PFREESID)( PSID pSid // SID to free
);
#endif // WINNT
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::CRegistry"
// CRegistry Constructor
//
// This is the default constructor for the registry class. It
// is used to construct a registry object which has not yet
// opened a handle to the registry. Open must be called before
// this object can be used.
//
// Parameters:
// N/A
//
// Returns:
// N/A
//
CRegistry::CRegistry( ): m_isOpen(FALSE), m_dwSignature(VSIG_CREGISTRY) { }
// CRegistry Destructor
//
// This is the destructor for the class, and will close the connection
// to the registry if this object has one open.
//
// Parameters:
// N/A
//
// Returns:
// N/A
//
CRegistry::~CRegistry() { if( m_isOpen ) { Close(); }
m_dwSignature = VSIG_CREGISTRY_FREE; }
// DeleteSubKey
//
// This function causes the key specified by the string equivalent of
// the pGuidName parameter to be deleted from the point in the registry
// this object is rooted at, if the key exists. If the object does not
// have an open connection to the registry, or the keyName is not specified
//
// Parmaters:
// const GUID *pGuidName - GUID whose equivalent string needs to be deleted
//
// Returns:
// BOOL - returns TRUE on success, FALSE on failure
//
BOOL CRegistry::DeleteSubKey( const GUID *pGuidName ) {
WCHAR wszGuidString[GUID_STRING_LEN]; DNASSERT( pGuidName != NULL );
// convert the guid to a string
if(!StringFromGUID2(*pGuidName, wszGuidString, GUID_STRING_LEN)) { DPFX(DPFPREP, 0, "StringFromGUID2 failed"); return FALSE; }
return DeleteSubKey(wszGuidString); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::DeleteSubKey"
// DeleteSubKey
//
// This function causes the key specified by the keyName parameter
// to be deleted from the point in the registry this object is rooted
// at, if the key exists. If the object does not have an open connection
// to the registry, or the keyName is not specified, FALSE is returned
//
// Parmaters:
// const TCHAR *keyName - key name to delete
//
// Returns:
// BOOL - returns TRUE on success, FALSE on failure
//
BOOL CRegistry::DeleteSubKey( const LPCWSTR keyName ) {
if( keyName == NULL || !IsOpen() ) { return FALSE; }
LONG retValue; #ifdef UNICODE
retValue = RegDeleteKeyW( m_regHandle, keyName ); #else
LPSTR lpstrKeyName;
if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) ) { return FALSE; } else { retValue = RegDeleteKeyA( m_regHandle, lpstrKeyName );
DNFree(lpstrKeyName); } #endif // UNICODE
return (retValue == ERROR_SUCCESS); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::DeleteValue"
// DeleteValue
//
// This function causes the value specified by the valueName parameter
// to be deleted from the point in the registry this object is rooted
// at, if the value exists. If the object does not have an open connection
// to the registry, or the valueName is not specified, FALSE is returned
//
// Parmaters:
// const TCHAR *keyName - key name to delete
//
// Returns:
// BOOL - returns TRUE on success, FALSE on failure
//
BOOL CRegistry::DeleteValue( const LPCWSTR valueName ) {
if( valueName == NULL || !IsOpen() ) return FALSE;
LONG retValue; #ifdef UNICODE
retValue = RegDeleteValueW( m_regHandle, valueName ); #else
LPSTR lpstrValueName;
if( FAILED( STR_AllocAndConvertToANSI( &lpstrValueName, valueName ) ) ) { return FALSE; } else { retValue = RegDeleteValueA( m_regHandle, lpstrValueName );
DNFree(lpstrValueName); } #endif // UNICODE
return (retValue == ERROR_SUCCESS); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::Open"
// Open
//
// This function opens a connection to the registry in the branch
// specified by branch with the path specified by pathName. If
// the path doesn't exist in the registry it will be created if
// the create parameters is set to true, otherwise the call will
// fail.
//
// If this object already has an open connection to the registry
// the previous connection will be closed before this one is
// attempted.
//
// Parameters:
// HKEY branch - A handle to a registry location where the open
// will be rooted. E.g. HKEY_LOCAL_MACHINE
// const TCHAR *path - The path relative to the root specified by
// branch where the registry connection will
// be opened.
// BOOL create - Settings this parameter conrols how this function
// handles opens on paths which don't exists. If set
// to TRUE the path will be created, if set to FALSE
// the function will fail if the path doesn't exist.
//
// Returns:
// BOOL - TRUE on success, FALSE on failure.
//
BOOL CRegistry::Open( HKEY branch, const LPCWSTR pathName, BOOL fReadOnly, BOOL create, BOOL fCustomSAM, REGSAM samCustom ) {
DWORD dwResult; // Temp used in call to RegXXXX
LONG result; // used to store results
if( pathName == NULL ) return FALSE;
// If there is an open connection, close it.
if( m_isOpen ) { Close(); }
m_fReadOnly = fReadOnly;
#ifdef UNICODE
// Create or open the key based on create parameter
if( create ) { result = RegCreateKeyExW( branch, pathName, 0, NULL, REG_OPTION_NON_VOLATILE, (fCustomSAM) ? samCustom : KEY_ALL_ACCESS, NULL, &m_regHandle, &dwResult ); } else { result = RegOpenKeyExW( branch, pathName, 0, (fReadOnly) ? KEY_READ : ((fCustomSAM) ? samCustom : KEY_ALL_ACCESS), &m_regHandle ); } #else
LPSTR lpszKeyName;
if( STR_AllocAndConvertToANSI( &lpszKeyName, pathName ) == S_OK && pathName ) { if( create ) { result = RegCreateKeyExA( branch, lpszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_regHandle, &dwResult ); } else { result = RegOpenKeyExA( branch, lpszKeyName, 0, (fReadOnly) ? KEY_READ : KEY_ALL_ACCESS, &m_regHandle ); }
DNFree(lpszKeyName); } else { return FALSE; } #endif // UNICODE
// If succesful, initialize object, otherwise set it to
// not open state.
if( result == ERROR_SUCCESS ) { m_isOpen = TRUE; m_baseHandle = branch; return TRUE;
} else { m_isOpen = FALSE; return FALSE; }
}
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::Open"
// Open
//
// This function opens a connection to the registry in the branch
// specified by branch with the path specified by pathName. If
// the path doesn't exist in the registry it will be created if
// the create parameters is set to true, otherwise the call will
// fail.
//
// In this version of the function, the path is specified as
// a guid instead of a string. The function will attempt to open
// a key with a name in the form "{CB4961DB-D2FA-43f3-942A-991D9294DDBB}"
// that corresponds to the guid as you would expect.
//
// If this object already has an open connection to the registry
// the previous connection will be closed before this one is
// attempted.
//
// Parameters:
// HKEY branch - A handle to a registry location where the open
// will be rooted. E.g. HKEY_LOCAL_MACHINE
// const LPGUID lpguid - The path relative to the root specified by
// branch where the registry connection will
// be opened. See comment above.
// BOOL create - Settings this parameter conrols how this function
// handles opens on paths which don't exists. If set
// to TRUE the path will be created, if set to FALSE
// the function will fail if the path doesn't exist.
//
// Returns:
// BOOL - TRUE on success, FALSE on failure.
//
BOOL CRegistry::Open( HKEY branch, const GUID* lpguid, BOOL fReadOnly, BOOL create, BOOL fCustomSAM, REGSAM samCustom ) { WCHAR wszGuidString[GUID_STRING_LEN]; DNASSERT( lpguid != NULL );
// convert the guid to a string
if (!StringFromGUID2(*lpguid, wszGuidString, GUID_STRING_LEN)) { DPFX(DPFPREP, 0, "StringFromGUID2 failed"); return FALSE; }
return Open(branch, wszGuidString, fReadOnly, create, fCustomSAM, samCustom); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::Close"
// Close
//
// This function will close an open connection to the registry
// if this object has one. Otherwise it does nothing.
//
// Parameters:
// N/A
//
// Returns:
// BOOL - Returns TRUE on success, FALSE on failure. If the object
// is not open it will return TRUE.
//
BOOL CRegistry::Close() {
LONG retValue;
if( m_isOpen ) { retValue = RegCloseKey( m_regHandle ); if( retValue == ERROR_SUCCESS ) { m_isOpen = FALSE; return TRUE; } else { return FALSE; } } else { return TRUE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::EnumKeys"
// EnumKeys
//
// This function can be used to enumerate the keys at the point
// in the registry rooted at the root this object was opened
// with, at the path specified when opening the object.
//
// To properly enumerate the keys you should pass 0 as the index on
// the first call, and increment the index parameter by one on each
// call. You can stop enumerating when the function returns FALSE.
//
// Parameters:
// LPWSTR lpwStrName - The current key in the enumeration will be returned
// in this string. Unless the enumeration fails or
// ended at which case this parameter won't be touched.
//
// LPDWORD lpdwStringLen - pointer to length of string buffer, or place to
// to store size required.
//
// DWORD index - The current enum index. See above for details.
//
// Returns:
// BOOL - FALSE when enumeration is done or on error, TRUE otherwise.
//
BOOL CRegistry::EnumKeys( LPWSTR lpwStrName, LPDWORD lpdwStringLen, DWORD index ) { #ifdef UNICODE
wchar_t buffer[MAX_REGISTRY_STRING_SIZE]; DWORD bufferSize = MAX_REGISTRY_STRING_SIZE; FILETIME tmpTime;
if( RegEnumKeyExW( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS ) { return FALSE; } else { if( bufferSize+1 > *lpdwStringLen ) { *lpdwStringLen = bufferSize+1; return FALSE; }
lstrcpyW( lpwStrName, buffer );
*lpdwStringLen = bufferSize+1; return TRUE; } #else
char buffer[MAX_REGISTRY_STRING_SIZE]; DWORD bufferSize = MAX_REGISTRY_STRING_SIZE; FILETIME tmpTime;
if( RegEnumKeyExA( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS ) { return FALSE; } else { if( bufferSize+1 > *lpdwStringLen ) { *lpdwStringLen = bufferSize+1; return FALSE; }
if( FAILED( STR_jkAnsiToWide( lpwStrName, buffer, *lpdwStringLen ) ) ) { return FALSE; } else { *lpdwStringLen = bufferSize+1; return TRUE; } } #endif // UNICODE
}
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::EnumValues"
// EnumValues
//
// This function can be used to enumerate the values at the point
// in the registry rooted at the root this object was opened
// with, at the path specified when opening the object.
//
// To properly enumerate the values you should pass 0 as the index on
// the first call, and increment the index parameter by one on each
// call. You can stop enumerating when the function returns FALSE.
//
// Parameters:
// LPWSTR lpwStrName - The current value in the enumeration will be returned
// in this string. Unless the enumeration fails or
// ended at which case this parameter won't be touched.
//
// LPDWORD lpdwStringLen - pointer to length of string buffer, or place to
// to store size required.
//
// DWORD index - The current enum index. See above for details.
//
// Returns:
// BOOL - FALSE when enumeration is done or on error, TRUE otherwise.
//
BOOL CRegistry::EnumValues( LPWSTR lpwStrName, LPDWORD lpdwStringLen, DWORD index ) { #ifdef UNICODE
wchar_t buffer[MAX_REGISTRY_STRING_SIZE]; DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
if( RegEnumValueW( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, NULL ) != ERROR_SUCCESS ) { return FALSE; } else { if( bufferSize+1 > *lpdwStringLen ) { *lpdwStringLen = bufferSize+1; return FALSE; }
lstrcpyW( lpwStrName, buffer );
*lpdwStringLen = bufferSize+1; return TRUE; } #else
char buffer[MAX_REGISTRY_STRING_SIZE]; DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
if( RegEnumValueA( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, NULL ) != ERROR_SUCCESS ) { return FALSE; } else { if( bufferSize+1 > *lpdwStringLen ) { *lpdwStringLen = bufferSize+1; return FALSE; }
if( FAILED( STR_jkAnsiToWide( lpwStrName, buffer, *lpdwStringLen ) ) ) { return FALSE; } else { *lpdwStringLen = bufferSize+1; return TRUE; } } #endif // UNICODE
}
// This comment documents ALL of the Read<Data Type> functions which
// follow.
//
// CRegistry Read<Data Type> Functions
//
// The set of ReadXXXXX functions for the CRegistry class are
// responsible for reading <data type> type data from the registry.
// The object must have an open connection to the registry before
// any of these functions may be used. A connection to the registry
// can be made with the Open call or the constructors.
//
// Parameters:
// const TCHAR *keyName - The keyname of the data you wish to read
// <datatype> & - A reference to the specific data type where
// the data will be placed on a succesful read.
// This parameter will be unaffected if the read
// fails.
//
// Returns:
// BOOL - Returns TRUE on success, FALSE on failure.
//
// This comment documents ALL of the Write<Data Type> functions which
// follow.
//
// CRegistry Write<Data Type> Functions
//
// The set of Write<Data Type> functions for the CRegistry class are
// responsible for writing <data type> type data to the registry.
// The object must have an open connection to the registry before
// any of these functions may be used. A connection to the registry
// can be made with the Open call or the constructors.
//
// Parameters:
// const TCHAR *keyName - The keyname of the data you wish to write
// <datatype> & - A reference to the specific data type which
// contains the data to be written to the registry.
//
// Returns:
// BOOL - Returns TRUE on success, FALSE on failure.
//
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::WriteString"
// WriteString
//
// Writes Strings's to the registry, see block comment above
// for details.
//
BOOL CRegistry::WriteString( LPCWSTR keyName, const LPCWSTR lpwstrValue ) {
LONG retValue; if( keyName == NULL || !IsOpen() || lpwstrValue == NULL ) { return FALSE; }
if( m_fReadOnly ) { DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key"); return FALSE; }
#ifdef UNICODE
retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) lpwstrValue, (lstrlenW( lpwstrValue )+1)*sizeof(wchar_t) ); #else
LPSTR lpstrKeyName; LPSTR lpstrValue; if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) ) { return FALSE; }
if( FAILED( STR_AllocAndConvertToANSI( &lpstrValue, lpwstrValue ) ) ) { DNFree(lpstrKeyName); return FALSE; } retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrValue, lstrlenA( lpstrValue )+1 );
DNFree(lpstrKeyName); DNFree(lpstrValue); #endif // UNICODE
return (retValue == ERROR_SUCCESS);
}
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::ReadString"
// ReadString
//
// Reads CString's from the registry, see block comment above
// for details.
//
BOOL CRegistry::ReadString( const LPCWSTR keyName, LPWSTR lpwstrValue, LPDWORD lpdwLength ) { if( keyName == NULL || !IsOpen() ) { return FALSE; }
LONG retValue; DWORD tmpSize; DWORD tmpType;
#ifdef UNICODE
wchar_t buffer[MAX_REGISTRY_STRING_SIZE]; tmpSize = MAX_REGISTRY_STRING_SIZE*sizeof(wchar_t); retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize ); if (retValue != ERROR_SUCCESS) { return FALSE; }
if( (tmpSize/2) > *lpdwLength || !lpwstrValue ) { *lpdwLength = (tmpSize/2); return FALSE; }
lstrcpyW( lpwstrValue, buffer );
*lpdwLength = (tmpSize/2);
return TRUE; #else
LPSTR lpstrKeyName; char buffer[MAX_REGISTRY_STRING_SIZE]; tmpSize = MAX_REGISTRY_STRING_SIZE;
if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) ) { return FALSE; } retValue = RegQueryValueExA( m_regHandle, lpstrKeyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize ); if (retValue != ERROR_SUCCESS) { DNFree(lpstrKeyName); return FALSE; }
DNFree(lpstrKeyName);
if( tmpSize > *lpdwLength || !lpwstrValue ) { *lpdwLength = tmpSize; return FALSE; }
if( FAILED( STR_jkAnsiToWide( lpwstrValue, buffer, *lpdwLength ) ) ) { return FALSE; }
*lpdwLength = tmpSize;
if( retValue == ERROR_SUCCESS && tmpType == REG_SZ ) { return TRUE; } else { return FALSE; } #endif // UNICODE
}
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::WriteGUID"
// WriteGUID
//
// Writes GUID's to the registry, see block comment above
// for details. The GUID is written in the format it is usually
// displayed. (But without the '{''s).
//
BOOL CRegistry::WriteGUID( LPCWSTR keyName, const GUID &guid ) { LONG retValue; WCHAR wszGuidString[GUID_STRING_LEN];
if( m_fReadOnly ) { DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key"); return FALSE; }
if (!StringFromGUID2(guid, wszGuidString, GUID_STRING_LEN)) { DPFX(DPFPREP, 0, "StringFromGUID2 failed"); return FALSE; }
#ifdef UNICODE
retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) wszGuidString, (lstrlenW( wszGuidString )+1)*sizeof(wchar_t) ); #else
HRESULT hr; LPSTR lpstrKeyName; LPSTR lpstrKeyValue;
hr = STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ); if (FAILED(hr)) { DPFX(DPFPREP, 0, "STR_AllocAndConvertToANSI failed, code: 0x%08x", hr); return FALSE; } hr = STR_AllocAndConvertToANSI( &lpstrKeyValue, wszGuidString ); if (FAILED(hr)) { DPFX(DPFPREP, 0, "STR_AllocAndConvertToANSI failed, code: 0x%08x", hr); DNFree(lpstrKeyName); return FALSE; }
retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrKeyValue, lstrlenA( lpstrKeyValue )+1);
DNFree(lpstrKeyName); DNFree(lpstrKeyValue); #endif // UNICODE
if( retValue == ERROR_SUCCESS ) { return TRUE; } else { return FALSE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::ReadGUID"
// ReadGUID
//
// Reads GUID's from the registry, see block comment above
// for details. The GUID must be stored in the format written by
// the WriteGUID function or it will not be read correctly.
//
BOOL CRegistry::ReadGUID( LPCWSTR keyName, GUID* pguid ) { wchar_t buffer[MAX_REGISTRY_STRING_SIZE]; DWORD dwLength = MAX_REGISTRY_STRING_SIZE; HRESULT hr;
if( !ReadString( keyName, buffer, &dwLength ) ) { return FALSE; } else { hr = CLSIDFromString(buffer, pguid); if (FAILED(hr)) { DPFX(DPFPREP, 0, "CLSIDFromString failed, code: 0x%08x", hr); return FALSE; } return TRUE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::WriteDWORD"
// WriteDWORD
//
// Writes DWORDS to the registry, see block comment above
// for details.
//
BOOL CRegistry::WriteDWORD( LPCWSTR keyName, DWORD value ) {
LONG retValue;
if( keyName == NULL || !IsOpen() ) { return FALSE; }
if( m_fReadOnly ) { DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key"); return FALSE; }
#ifdef UNICODE
retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) ); #else
LPSTR lpszKeyName;
if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) ) { return FALSE; }
retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) );
DNFree(lpszKeyName); #endif // UNICODE
return (retValue == ERROR_SUCCESS); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::ReadDWORD"
// ReadDWORD
//
// Reads DWORDS from the registry, see block comment above
// for details.
//
BOOL CRegistry::ReadDWORD( LPCWSTR keyName, DWORD* presult ) {
if( keyName == NULL || !IsOpen() ) { return FALSE; }
LONG retValue; DWORD tmpValue; DWORD tmpType; DWORD tmpSize;
tmpSize = sizeof( DWORD );
#ifdef UNICODE
retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize ); #else
LPSTR lpszKeyName;
if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) ) { return FALSE; }
retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize ); DNFree(lpszKeyName); #endif // UNICODE
if( retValue == ERROR_SUCCESS && (tmpType == REG_DWORD || tmpType == REG_BINARY) && tmpSize == sizeof(DWORD) ) { *presult = tmpValue; return TRUE; } else { return FALSE; } }
#ifndef DPNBUILD_NOCOMREGISTER
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::Register"
BOOL CRegistry::Register( LPCWSTR lpszProgID, const LPCWSTR lpszDesc, const LPCWSTR lpszProgName, const GUID* pguidCLSID, LPCWSTR lpszVerIndProgID ) { CRegistry core;
DNASSERT( lpszDesc != NULL ); DNASSERT( lpszProgID != NULL );
// Build a string representation of the GUID from the GUID
wchar_t lpszGUID[GUID_STRING_LEN]; wchar_t lpszKeyName[_MAX_PATH];
// convert the guid to a string
if (!StringFromGUID2(*pguidCLSID, lpszGUID, GUID_STRING_LEN)) { DPFX(DPFPREP, 0, "StringFromGUID2 failed"); return FALSE; }
// Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create registry key \"%ls\"", lpszKeyName ); return FALSE; }
core.WriteString( L"", lpszDesc ); core.Close();
// Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\InProcServer32 section
swprintf( lpszKeyName, L"CLSID\\%s\\InProcServer32", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create registry key \"%ls\"", lpszKeyName ); return FALSE; } core.WriteString( L"", lpszProgName ); core.WriteString( L"ThreadingModel", L"Both" ); core.Close();
// Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\VersionIndependentProgID section
if( lpszVerIndProgID != NULL ) { swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create verind registry key \"%ls\"", lpszKeyName ); return FALSE; } core.WriteString( L"", lpszVerIndProgID ); core.Close(); }
// Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\ProgID section
swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create verind registry key \"%ls\"", lpszKeyName ); return FALSE; }
core.WriteString( L"", lpszProgID ); core.Close();
// Write The VersionIND ProgID
if( lpszVerIndProgID != NULL ) { if( !core.Open( HKEY_CLASSES_ROOT, lpszVerIndProgID, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszVerIndProgID ); } else { core.WriteString( L"", lpszDesc ); core.Close(); }
swprintf( lpszKeyName, L"%s\\CLSID", lpszVerIndProgID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName ); } else { core.WriteString( L"", lpszGUID ); core.Close(); }
swprintf( lpszKeyName, L"%s\\CurVer", lpszVerIndProgID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName ); } else { core.WriteString( L"", lpszProgID ); core.Close(); } }
if( !core.Open( HKEY_CLASSES_ROOT, lpszProgID, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName ); } else { core.WriteString( L"", lpszDesc ); core.Close(); } swprintf( lpszKeyName, L"%s\\CLSID", lpszProgID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) ) { DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName ); } else { core.WriteString( L"", lpszGUID ); core.Close(); }
return TRUE; }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::UnRegister"
BOOL CRegistry::UnRegister( const GUID* pguidCLSID ) { CRegistry core, cregClasses, cregSub;
// Build a string representation of the GUID from the GUID
wchar_t lpszGUID[GUID_STRING_LEN]; wchar_t lpszKeyName[_MAX_PATH]; wchar_t szProgID[MAX_REGISTRY_STRING_SIZE]; wchar_t szVerIndProgID[MAX_REGISTRY_STRING_SIZE]; DWORD dwSize = MAX_REGISTRY_STRING_SIZE;
// convert the guid to a string
if (!StringFromGUID2(*pguidCLSID, lpszGUID, GUID_STRING_LEN)) { DPFX(DPFPREP, 0, "StringFromGUID2 failed"); return FALSE; }
if( !cregClasses.Open( HKEY_CLASSES_ROOT, L"", FALSE, FALSE ) ) { DPFX(DPFPREP, 0, "Unable to open HKEY_CLASSES_ROOT" ); return FALSE; }
// Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, FALSE ) ) { DPFX(DPFPREP, 0, "Unable to open \"%ls\"", lpszKeyName ); return FALSE; }
dwSize = MAX_REGISTRY_STRING_SIZE;
if( core.ReadString( L"", szProgID, &dwSize ) ) { swprintf( lpszKeyName, L"%s\\CLSID", szProgID ); if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; } if( !cregClasses.DeleteSubKey( szProgID ) ) { DPFX(DPFPREP, 0, "Unable to delete HKEY_CLASSES_ROOT/ProgID" );
return FALSE; } }
core.Close();
swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, FALSE ) ) { DPFX(DPFPREP, 0, "Unable to open \"%ls\"", lpszKeyName ); return FALSE; }
dwSize = MAX_REGISTRY_STRING_SIZE; if( core.ReadString( L"", szVerIndProgID, &dwSize ) ) { swprintf( lpszKeyName, L"%s\\CLSID", szVerIndProgID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; }
swprintf( lpszKeyName, L"%s\\CurVer", szVerIndProgID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; } if( !cregClasses.DeleteSubKey( szVerIndProgID ) ) { DPFX(DPFPREP, 0, "Unable to delete \"HKEY_CLASSES_ROOT/%ls\"", szVerIndProgID);
return FALSE; } }
core.Close();
swprintf( lpszKeyName, L"CLSID\\%s\\InprocServer32", lpszGUID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; } swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; } swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; }
swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
if( !cregClasses.DeleteSubKey( lpszKeyName ) ) { DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName ); return FALSE; }
return TRUE; }
#endif // !DPNBUILD_NOCOMREGISTER
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::ReadBlob"
BOOL CRegistry::ReadBlob( LPCWSTR keyName, LPBYTE lpbBuffer, LPDWORD lpdwSize ) { if( keyName == NULL || !IsOpen() ) return FALSE;
LONG retValue; DWORD tmpType;
#ifdef UNICODE
retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, lpbBuffer, lpdwSize ); #else
LPSTR lpszKeyName; if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) ) { return FALSE; }
retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, lpbBuffer, lpdwSize );
DNFree(lpszKeyName); #endif // UNICODE
if( retValue == ERROR_SUCCESS && tmpType == REG_BINARY ) { return TRUE; } else { return FALSE; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::WriteBlob"
BOOL CRegistry::WriteBlob( LPCWSTR keyName, const BYTE* const lpbBuffer, DWORD dwSize ) { LONG retValue;
if( keyName == NULL || !IsOpen() ) { return FALSE; }
if( m_fReadOnly ) { DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key"); return FALSE; }
#ifdef UNICODE
retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_BINARY, lpbBuffer, dwSize ); #else
LPSTR lpszKeyName; if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) ) return FALSE;
retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_BINARY, lpbBuffer, dwSize ); DNFree(lpszKeyName); #endif // UNICODE
return (retValue == ERROR_SUCCESS); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::GetMaxKeyLen"
BOOL CRegistry::GetMaxKeyLen( DWORD* pdwMaxKeyLen ) { LONG retVal;
#ifdef UNICODE
retVal = RegQueryInfoKeyW( m_regHandle,NULL,NULL,NULL,NULL,pdwMaxKeyLen, NULL,NULL,NULL,NULL,NULL,NULL); #else
retVal = RegQueryInfoKeyA( m_regHandle,NULL,NULL,NULL,NULL,pdwMaxKeyLen, NULL,NULL,NULL,NULL,NULL,NULL); #endif // UNICODE
return (retVal == ERROR_SUCCESS); }
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::GetValueLength"
// GetValueLength
//
// Determines the length of a particular key value
//
BOOL CRegistry::GetValueLength( const LPCWSTR keyName, DWORD *const pdwValueLength ) { LONG retValue; DWORD tmpLength;
if ( keyName == NULL || pdwValueLength == NULL || !IsOpen() ) { return FALSE; }
#ifdef UNICODE
DWORD dwType; retValue = RegQueryValueExW( m_regHandle, keyName, 0, &dwType, NULL, &tmpLength ); if (retValue != ERROR_SUCCESS) { return FALSE; }
//
// if this is a string, we need to compensate for WCHAR characters being
// returned
//
if ( dwType == REG_SZ ) { tmpLength /= sizeof( WCHAR ); } #else
LPSTR lpstrKeyName;
if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) ) { return FALSE; } retValue = RegQueryValueExA( m_regHandle, lpstrKeyName, 0, NULL, NULL, &tmpLength );
DNFree(lpstrKeyName);
if (retValue != ERROR_SUCCESS) { return FALSE; } #endif // UNICODE
*pdwValueLength = tmpLength;
return TRUE; }
#ifdef WINNT
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::GrantAllAccessSecurityPermissions"
// GrantAllAccessSecurityPermissions
//
// Gives the given key all access for everyone rights
//
// Taken from hresMumbleKeyEx in diregutl.c in the dinput tree.
//
BOOL CRegistry::GrantAllAccessSecurityPermissions() { BOOL fResult = FALSE; HRESULT hr; EXPLICIT_ACCESS ExplicitAccess; PACL pACL = NULL; PSID pSid = NULL; HMODULE hModuleADVAPI32 = NULL; SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY; PALLOCATEANDINITIALIZESID pAllocateAndInitializeSid = NULL; PBUILDTRUSTEEWITHSID pBuildTrusteeWithSid = NULL; PSETENTRIESINACL pSetEntriesInAcl = NULL; PSETSECURITYINFO pSetSecurityInfo = NULL; PFREESID pFreeSid = NULL;
hModuleADVAPI32 = LoadLibrary( _T("advapi32.dll") );
if( !hModuleADVAPI32 ) { DPFX(DPFPREP, 0, "Failed loading advapi32.dll" ); goto EXIT; }
pFreeSid = reinterpret_cast<PFREESID>( GetProcAddress( hModuleADVAPI32, "FreeSid" ) ); pSetSecurityInfo = reinterpret_cast<PSETSECURITYINFO>( GetProcAddress( hModuleADVAPI32, "SetSecurityInfo" ) ); pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>( GetProcAddress( hModuleADVAPI32, "SetEntriesInAclA" ) ); pBuildTrusteeWithSid = reinterpret_cast<PBUILDTRUSTEEWITHSID>( GetProcAddress( hModuleADVAPI32, "BuildTrusteeWithSidA" ) ); pAllocateAndInitializeSid = reinterpret_cast<PALLOCATEANDINITIALIZESID>( GetProcAddress( hModuleADVAPI32, "AllocateAndInitializeSid" ) );
if( !pFreeSid || !pSetSecurityInfo || !pSetEntriesInAcl || !pBuildTrusteeWithSid || !pAllocateAndInitializeSid ) { DPFX(DPFPREP, 0, "Failed loading entry points" ); goto EXIT; }
// Describe the access we want to create the key with
ZeroMemory (&ExplicitAccess, sizeof(ExplicitAccess) ); ExplicitAccess.grfAccessPermissions = ((KEY_ALL_ACCESS & ~WRITE_DAC) & ~WRITE_OWNER); /*KEY_QUERY_VALUE | KEY_SET_VALUE
| KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK | DELETE | READ_CONTROL; */ ExplicitAccess.grfAccessMode = SET_ACCESS; // discard any existing AC info
ExplicitAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
if (pAllocateAndInitializeSid( &authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSid )) { pBuildTrusteeWithSid(&(ExplicitAccess.Trustee), pSid );
hr = pSetEntriesInAcl( 1, &ExplicitAccess, NULL, &pACL );
if( hr == ERROR_SUCCESS ) { hr = pSetSecurityInfo( m_regHandle, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Unable to set security for key. Error! hr=0x%x", hr ); } else { fResult = TRUE; } } else { DPFX(DPFPREP, 0, "SetEntriesInACL failed, hr=0x%x", hr ); } } else { hr = GetLastError(); DPFX(DPFPREP, 0, "AllocateAndInitializeSid failed lastError=0x%x", hr ); }
EXIT:
if( pACL ) { LocalFree( pACL ); }
//Cleanup pSid
if (pSid != NULL) { (pFreeSid)(pSid); }
if( hModuleADVAPI32 ) { FreeLibrary( hModuleADVAPI32 ); }
return fResult; }
#endif // WINNT
#ifdef WINNT
#undef DPF_MODNAME
#define DPF_MODNAME "CRegistry::RemoveAllAccessSecurityPermissions"
// RemoveAllAccessSecurityPermissions
//
// Removes "all access for everyone" rights from the specified key.
// This is identical to GrantAllAccessSecurityPermissions(), except that
// now we REVOKE_ACCESS instead of SET_ACCESS, and we don't have to fill
// out the rest of the EXPLICIT_ACCESS struct.
//
//
BOOL CRegistry::RemoveAllAccessSecurityPermissions() { BOOL fResult = FALSE; HRESULT hr; EXPLICIT_ACCESS ExplicitAccess; PACL pACL = NULL; PSID pSid = NULL; HMODULE hModuleADVAPI32 = NULL; SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY; PALLOCATEANDINITIALIZESID pAllocateAndInitializeSid = NULL; PBUILDTRUSTEEWITHSID pBuildTrusteeWithSid = NULL; PSETENTRIESINACL pSetEntriesInAcl = NULL; PSETSECURITYINFO pSetSecurityInfo = NULL; PFREESID pFreeSid = NULL;
hModuleADVAPI32 = LoadLibrary( _T("advapi32.dll") );
if( !hModuleADVAPI32 ) { DPFX(DPFPREP, 0, "Failed loading advapi32.dll" ); goto EXIT; }
pFreeSid = reinterpret_cast<PFREESID>( GetProcAddress( hModuleADVAPI32, "FreeSid" ) ); pSetSecurityInfo = reinterpret_cast<PSETSECURITYINFO>( GetProcAddress( hModuleADVAPI32, "SetSecurityInfo" ) ); pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>( GetProcAddress( hModuleADVAPI32, "SetEntriesInAclA" ) ); pBuildTrusteeWithSid = reinterpret_cast<PBUILDTRUSTEEWITHSID>( GetProcAddress( hModuleADVAPI32, "BuildTrusteeWithSidA" ) ); pAllocateAndInitializeSid = reinterpret_cast<PALLOCATEANDINITIALIZESID>( GetProcAddress( hModuleADVAPI32, "AllocateAndInitializeSid" ) );
if( !pFreeSid || !pSetSecurityInfo || !pSetEntriesInAcl || !pBuildTrusteeWithSid || !pAllocateAndInitializeSid ) { DPFX(DPFPREP, 0, "Failed loading entry points" ); goto EXIT; }
ZeroMemory (&ExplicitAccess, sizeof(ExplicitAccess) ); ExplicitAccess.grfAccessMode = REVOKE_ACCESS; //Remove any existing ACEs for the specified trustee
if (pAllocateAndInitializeSid( &authority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, // trustee is "Everyone"
&pSid )) { pBuildTrusteeWithSid(&(ExplicitAccess.Trustee), pSid );
hr = pSetEntriesInAcl( 1, &ExplicitAccess, NULL, &pACL );
if( hr == ERROR_SUCCESS ) { hr = pSetSecurityInfo( m_regHandle, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Unable to set security for key. Error! hr=0x%x", hr ); } else { fResult = TRUE; } } else { DPFX(DPFPREP, 0, "SetEntriesInACL failed, hr=0x%x", hr ); } } else { hr = GetLastError(); DPFX(DPFPREP, 0, "AllocateAndInitializeSid failed lastError=0x%x", hr ); }
EXIT:
if( pACL ) { LocalFree( pACL ); }
//Cleanup pSid
if (pSid != NULL) { (pFreeSid)(pSid); }
if( hModuleADVAPI32 ) { FreeLibrary( hModuleADVAPI32 ); }
return fResult; }
#endif // WINNT
#endif // ! DPNBUILD_NOREGISTRY
|