// Helper functions for handling the registry #pragma once // Used behind CopyIfMatch. Copies a given registry value to // another location, regardless of type. BOOL CopyRegValue(HKEY hKey, PVOID pVal, LPCTSTR szName, DWORD dwType, DWORD dwSize); // Callback for RegGetAllValues typedef BOOL (*RegEnumCallback)(HKEY hKey, LPTSTR szValName, DWORD dwValSize, DWORD dwValType, PVOID pData); // Enumerates across all values in a key, running the given // RegEnumCallback. Use `pData` to pass application-defined // data to your enumerator callback. BOOL RegGetAllValues(HKEY hKey, RegEnumCallback cb, PVOID pData); // Wrapper function for storing reg values, regardless of type BOOL RegStoreValue(HKEY hKey, LPTSTR szValName, PVOID pData, DWORD dwValType); // Used primarily by RegEnumCallback, hence the hardcoded // var names. // You might want to check out one of the Get*Config functions // for more background on how to use this, but it should make the // callback function as easy as: // // CopyIfMatch(hKey, myStruct, // myField, REG_SZ) // or any type // else CopyIfMatch(hKey, myStruct, // myOtherField, REG_DWORD) // also note: no semicolons // // ... and so on #define CopyIfMatch(hk,x,name,type) \ if (!_tcsncmp(_T(#name), \ szValName, \ _tcslen(_T(#name))) \ && (dwValType & 0xfff) == type) { \ if (!CopyRegValue(hk, \ &((x)->name), \ _T(#name), \ type, \ dwValSize)) { \ return FALSE; \ } \ } // Helper macro for Save*Config functions. Assumes a BOOL-returning // function in a vacuum. #define StoreConfig(hk,x,name,type) \ if (!RegStoreValue(hk, _T(#name), &(x)->name, type)) { \ DWORD dwRegErr = GetLastError(); \ RegCloseKey(hk); \ return FALSE; \ } #define ROOT_KEYNAME "SOFTWARE\\Grabby" // Hack to handle REG_SZ values that are actually TCHAR[MAX_PATH]. #define REG_PATH_SZ (0xf000 & REG_SZ)