/* * Rufus: The Reliable USB Formatting Utility * Registry access * Copyright © 2012-2015 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "rufus.h" #pragma once #ifdef __cplusplus extern "C" { #endif #define REGKEY_HKCU HKEY_CURRENT_USER #define REGKEY_HKLM HKEY_LOCAL_MACHINE /* Delete a registry key from \Software and all its values If the key has subkeys, this call will fail. */ static __inline BOOL DeleteRegistryKey(HKEY key_root, const char* key_name) { HKEY hSoftware = NULL; LONG s; if (RegOpenKeyExA(key_root, "SOFTWARE", 0, KEY_READ|KEY_CREATE_SUB_KEY, &hSoftware) != ERROR_SUCCESS) { return FALSE; } s = RegDeleteKeyA(hSoftware, key_name); if ((s != ERROR_SUCCESS) && (s != ERROR_FILE_NOT_FOUND)) { SetLastError(s); uprintf("Failed to delete registry key HKCU\\Software\\%s: %s", key_name, (s == ERROR_ACCESS_DENIED)?"Key is not empty":WindowsErrorString()); } RegCloseKey(hSoftware); return ((s == ERROR_SUCCESS) || (s == ERROR_FILE_NOT_FOUND)); } /* Read a generic registry key value. If a short key_name is used, assume that it belongs to the application and create the app subkey if required */ static __inline BOOL _GetRegistryKey(HKEY key_root, const char* key_name, DWORD reg_type, LPBYTE dest, DWORD dest_size) { BOOL r = FALSE; size_t i = 0; LONG s; HKEY hSoftware = NULL, hApp = NULL; DWORD dwDisp, dwType = -1, dwSize = dest_size; // VS Code Analysis complains if we don't break our initialization into chars char long_key_name[256] = { 0 }; memset(dest, 0, dest_size); if (key_name == NULL) return FALSE; for (i=safe_strlen(key_name); i>0; i--) { if (key_name[i] == '\\') break; } if (i != 0) { strcpy(long_key_name, "SOFTWARE\\"); safe_strcat(long_key_name, sizeof(long_key_name), key_name); long_key_name[sizeof("SOFTWARE\\") + i-1] = 0; i++; if (RegOpenKeyExA(key_root, long_key_name, 0, KEY_READ, &hApp) != ERROR_SUCCESS) { hApp = NULL; goto out; } } else { if (RegOpenKeyExA(key_root, "SOFTWARE", 0, KEY_READ|KEY_CREATE_SUB_KEY, &hSoftware) != ERROR_SUCCESS) { hSoftware = NULL; goto out; } if (RegCreateKeyExA(hSoftware, COMPANY_NAME "\\" APPLICATION_NAME, 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hApp, &dwDisp) != ERROR_SUCCESS) { hApp = NULL; goto out; } } s = RegQueryValueExA(hApp, &key_name[i], NULL, &dwType, (LPBYTE)dest, &dwSize); // No key means default value of 0 or empty string if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType = reg_type) && (dwSize > 0))) { r = TRUE; } out: if (hSoftware != NULL) RegCloseKey(hSoftware); if (hApp != NULL) RegCloseKey(hApp); return r; } /* Write a generic registry key value (create the key if it doesn't exist) */ static __inline BOOL _SetRegistryKey(HKEY key_root, const char* key_name, DWORD reg_type, LPBYTE src, DWORD src_size) { BOOL r = FALSE; HKEY hSoftware = NULL, hApp = NULL; DWORD dwDisp, dwType = reg_type; if (RegOpenKeyExA(key_root, "SOFTWARE", 0, KEY_READ|KEY_CREATE_SUB_KEY, &hSoftware) != ERROR_SUCCESS) { hSoftware = NULL; goto out; } if (RegCreateKeyExA(hSoftware, COMPANY_NAME "\\" APPLICATION_NAME, 0, NULL, 0, KEY_SET_VALUE|KEY_QUERY_VALUE|KEY_CREATE_SUB_KEY, NULL, &hApp, &dwDisp) != ERROR_SUCCESS) { hApp = NULL; goto out; } r = (RegSetValueExA(hApp, key_name, 0, dwType, src, src_size) == ERROR_SUCCESS); out: if (hSoftware != NULL) RegCloseKey(hSoftware); if (hApp != NULL) RegCloseKey(hApp); return r; } /* Helpers for 64 bit registry operations */ #define GetRegistryKey64(root, key, pval) _GetRegistryKey(root, key, REG_QWORD, (LPBYTE)pval, sizeof(LONGLONG)) #define SetRegistryKey64(root, key, val) _SetRegistryKey(root, key, REG_QWORD, (LPBYTE)&val, sizeof(LONGLONG)) // Check that a key is accessible for R/W (will create a key if not already existing) static __inline BOOL CheckRegistryKey64(HKEY root, const char* key) { LONGLONG val; return GetRegistryKey64(root, key, &val); } static __inline int64_t ReadRegistryKey64(HKEY root, const char* key) { LONGLONG val; GetRegistryKey64(root, key, &val); return (int64_t)val; } static __inline BOOL WriteRegistryKey64(HKEY root, const char* key, int64_t val) { LONGLONG tmp = (LONGLONG)val; return SetRegistryKey64(root, key, tmp); } /* Helpers for 32 bit registry operations */ #define GetRegistryKey32(root, key, pval) _GetRegistryKey(root, key, REG_DWORD, (LPBYTE)pval, sizeof(DWORD)) #define SetRegistryKey32(root, key, val) _SetRegistryKey(root, key, REG_DWORD, (LPBYTE)&val, sizeof(DWORD)) static __inline BOOL CheckRegistryKey32(HKEY root, const char* key) { DWORD val; return (GetRegistryKey32(root, key, &val) && SetRegistryKey32(root, key, val)); } static __inline int32_t ReadRegistryKey32(HKEY root, const char* key) { DWORD val; GetRegistryKey32(root, key, &val); return (int32_t)val; } static __inline BOOL WriteRegistryKey32(HKEY root, const char* key, int32_t val) { DWORD tmp = (DWORD)val; return SetRegistryKey32(root, key, tmp); } /* Helpers for boolean registry operations */ #define ReadRegistryKeyBool(root, key) (ReadRegistryKey32(root, key) != 0) #define WriteRegistryKeyBool(root, key, b) WriteRegistryKey32(root, key, (b)?1:0) #define CheckRegistryKeyBool CheckRegistryKey32 /* Helpers for String registry operations */ #define GetRegistryKeyStr(root, key, str, len) _GetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)len) #define SetRegistryKeyStr(root, key, str) _SetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)safe_strlen(str)) // Use a static buffer - don't allocate static __inline char* ReadRegistryKeyStr(HKEY root, const char* key) { static char str[512]; str[0] = 0; _GetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)sizeof(str)-1); return str; } #define WriteRegistryKeyStr SetRegistryKeyStr #ifdef __cplusplus } #endif