Sign in to follow this  
Seriema

Win32 API registry operations wrapper

Recommended Posts

Hi yall! I'm up to my ears with my pet project. It requires some writing to the registry since it's a shell extension. I ended up writing a wrapper for all those RegX(). I'm kinda happy with it so I thougth I'd share it with you! RegOps.h
#ifndef __REGOPS_H_
#define __REGOPS_H_

#include <string>
#include <vector>
#include <iterator>
#include <ShlObj.h>

//#define VC_EXTRALEAN
//#include <Windows.h>


class RegOps
{
	typedef std::basic_string<TCHAR> tstring;
public:

	RegOps( HKEY hStartKey ) : hKey( hStartKey ) {}
	~RegOps() { if(hKey) CloseKey(); }

	inline bool CreateKey( LPCTSTR lpSubKey )
	{
		Trace( "RegCreateKeyEx", lpSubKey );
		return CheckRegOp( RegCreateKeyEx( hKey, lpSubKey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL ) );
	}

	inline bool OpenKey( LPCTSTR lpSubKey )
	{
		Trace( "RegOpenKeyEx", lpSubKey );
		return CheckRegOp( RegOpenKeyEx( hKey, lpSubKey,  0, KEY_READ, &hKey ) );
	}

	/* other types of SetXValue that could be implemented on need: REG_BINARY,	REG_DWORD, REG_NONE */
	inline bool SetStringValue( LPCTSTR lpValueName, const tstring& sData )
	{
		tstring desc( lpValueName ? lpValueName : "Default value" );
		desc.append(" = " + sData);
		Trace( "RegSetValueEx", desc );
		return CheckRegOp( RegSetValueEx( hKey, lpValueName, 0, REG_SZ, reinterpret_cast<const BYTE*>(sData.c_str()), static_cast<DWORD>( sData.size() + 1) ) );
	}

	//inline bool QueryValue( LPCTSTR lpValueName, tstring& outData )
	inline bool QueryValue( LPCTSTR lpValueName, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData )
	{
		Trace( "RegQueryValueEx", lpValueName );
		return CheckRegOp( RegQueryValueEx( hKey, lpValueName, NULL, lpType, lpData, lpcbData) );
	}


	inline bool DeleteKey( LPCTSTR lpSubKey )
	{
		Trace( "RegDeleteKey", lpSubKey );
		return CheckRegOp( RegDeleteKey( hKey, lpSubKey ) );
	}

	inline bool DeleteValue( LPCTSTR lpValueName )
	{
		Trace( "RegDeleteValue", lpValueName );
		return CheckRegOp( RegDeleteValue( hKey, lpValueName ) );
	}

	inline bool FlushKey()
	{
		Trace( "RegFlushKey" );
		return CheckRegOp( RegFlushKey( hKey ) );
	}

	inline bool CloseKey()
	{
		Trace( "RegCloseKey" );
		bool res = CheckRegOp( RegCloseKey( hKey ) );
		hKey = NULL;
		return res;
	}

	inline static void NotifyWindows()
	{
		//Trace( "SHChangeNotify" );
		SHChangeNotify( SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL );
	}


private:
	HKEY hKey;

#ifdef _DEBUG
	typedef std::vector< tstring > traceType;
	traceType trace;
#endif

	bool CheckRegOp( DWORD returnCode )
	{
		if( returnCode != ERROR_SUCCESS )
		{
#ifdef _DEBUG
			tstring err;
			err.append( "ThumbView - Registry operation failed: " + FormatError(returnCode) + "\n" );
			err.append( "\nTrace:\n" );
			for( traceType::reverse_iterator t = trace.rbegin(); t != trace.rend(); ++t )
				err.append( *t + "\n" );
			//std::copy( trace.begin(), trace.end(), std::inserter(err, err.end()) );
			OutputDebugString( err.c_str() );
#endif
			return false;
		}
		return true;
	}

	void Trace( const tstring& funcName, const tstring& params = tstring() )
	{
#ifdef _DEBUG
		if( params.empty() )
			trace.push_back( funcName );
		else
			trace.push_back( funcName + " - " + params );
#endif
	}

};

#endif  // __REGOPS_H_





A helper function for formating errors used in RegOps::CheckRegOp(), FormatError(). But it's useful for other applications as well.
std::string FormatError( DWORD errorCode )
{
	LPVOID lpMsgBuf = 0;
	DWORD buffSize = FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		FORMAT_MESSAGE_FROM_SYSTEM | 
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		errorCode,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL );
	if( !buffSize )
		return FormatError( GetLastError() );

	std::string formatted = (LPTSTR)lpMsgBuf;
	LocalFree( lpMsgBuf );

	return formatted;
}





It's fairly easy to use. Just do RegOps reg( HKEY_CLASSES_ROOT ); // or any other predefined key reg.CreateKey( "name of key" ); reg.SetStringValue( "name of variable", "data" ); reg.Flush(); // this one's costly, read MSDN reg.Close(); // if you don't close the dtor will do it for you Done! All comments and suggestions are welcome :) [Edited by - Seriema on September 20, 2004 3:12:27 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this