2012-11-08 01:20:48 +00:00
|
|
|
/*
|
|
|
|
* Rufus: The Reliable USB Formatting Utility
|
|
|
|
* Registry access
|
2015-01-23 02:26:41 +00:00
|
|
|
* Copyright © 2012-2015 Pete Batard <pete@akeo.ie>
|
2012-11-08 01:20:48 +00:00
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdint.h>
|
2012-11-22 01:52:33 +00:00
|
|
|
#include "rufus.h"
|
2012-11-08 01:20:48 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2013-02-02 16:57:46 +00:00
|
|
|
#define REGKEY_HKCU HKEY_CURRENT_USER
|
|
|
|
#define REGKEY_HKLM HKEY_LOCAL_MACHINE
|
|
|
|
|
|
|
|
/* Delete a registry key from <key_root>\Software and all its values
|
2012-11-22 01:52:33 +00:00
|
|
|
If the key has subkeys, this call will fail. */
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL DeleteRegistryKey(HKEY key_root, const char* key_name)
|
2012-11-22 01:52:33 +00:00
|
|
|
{
|
|
|
|
HKEY hSoftware = NULL;
|
2012-11-29 02:59:52 +00:00
|
|
|
LONG s;
|
2012-11-22 01:52:33 +00:00
|
|
|
|
2013-02-02 16:57:46 +00:00
|
|
|
if (RegOpenKeyExA(key_root, "SOFTWARE", 0, KEY_READ|KEY_CREATE_SUB_KEY, &hSoftware) != ERROR_SUCCESS) {
|
2012-11-22 01:52:33 +00:00
|
|
|
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));
|
|
|
|
}
|
2012-11-08 01:20:48 +00:00
|
|
|
|
2013-01-20 22:46:11 +00:00
|
|
|
/* 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 */
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL _GetRegistryKey(HKEY key_root, const char* key_name, DWORD reg_type, LPBYTE dest, DWORD dest_size)
|
2012-11-08 01:20:48 +00:00
|
|
|
{
|
|
|
|
BOOL r = FALSE;
|
2013-01-20 22:46:11 +00:00
|
|
|
size_t i = 0;
|
2012-11-08 01:20:48 +00:00
|
|
|
LONG s;
|
|
|
|
HKEY hSoftware = NULL, hApp = NULL;
|
|
|
|
DWORD dwDisp, dwType = -1, dwSize = dest_size;
|
2015-08-10 22:19:57 +00:00
|
|
|
// VS Code Analysis complains if we don't break our initialization into chars
|
|
|
|
char long_key_name[256] = { 0 };
|
2012-11-08 01:20:48 +00:00
|
|
|
memset(dest, 0, dest_size);
|
|
|
|
|
2015-08-10 22:19:57 +00:00
|
|
|
if (key_name == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2013-01-20 22:46:11 +00:00
|
|
|
for (i=safe_strlen(key_name); i>0; i--) {
|
|
|
|
if (key_name[i] == '\\')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i != 0) {
|
2015-08-10 22:19:57 +00:00
|
|
|
strcpy(long_key_name, "SOFTWARE\\");
|
2013-01-20 22:46:11 +00:00
|
|
|
safe_strcat(long_key_name, sizeof(long_key_name), key_name);
|
|
|
|
long_key_name[sizeof("SOFTWARE\\") + i-1] = 0;
|
|
|
|
i++;
|
2015-01-23 02:26:41 +00:00
|
|
|
if (RegOpenKeyExA(key_root, long_key_name, 0, KEY_READ, &hApp) != ERROR_SUCCESS) {
|
|
|
|
hApp = NULL;
|
2013-01-20 22:46:11 +00:00
|
|
|
goto out;
|
2015-01-23 02:26:41 +00:00
|
|
|
}
|
2013-01-20 22:46:11 +00:00
|
|
|
} else {
|
2015-01-23 02:26:41 +00:00
|
|
|
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;
|
|
|
|
}
|
2012-11-08 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2013-01-20 22:46:11 +00:00
|
|
|
s = RegQueryValueExA(hApp, &key_name[i], NULL, &dwType, (LPBYTE)dest, &dwSize);
|
2012-11-08 01:20:48 +00:00
|
|
|
// No key means default value of 0 or empty string
|
2013-01-20 22:46:11 +00:00
|
|
|
if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType = reg_type) && (dwSize > 0))) {
|
2012-11-08 01:20:48 +00:00
|
|
|
r = TRUE;
|
|
|
|
}
|
|
|
|
out:
|
2015-01-23 02:26:41 +00:00
|
|
|
if (hSoftware != NULL)
|
|
|
|
RegCloseKey(hSoftware);
|
|
|
|
if (hApp != NULL)
|
|
|
|
RegCloseKey(hApp);
|
2012-11-08 01:20:48 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2012-11-22 01:52:33 +00:00
|
|
|
/* Write a generic registry key value (create the key if it doesn't exist) */
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL _SetRegistryKey(HKEY key_root, const char* key_name, DWORD reg_type, LPBYTE src, DWORD src_size)
|
2012-11-08 01:20:48 +00:00
|
|
|
{
|
|
|
|
BOOL r = FALSE;
|
|
|
|
HKEY hSoftware = NULL, hApp = NULL;
|
|
|
|
DWORD dwDisp, dwType = reg_type;
|
|
|
|
|
2015-01-23 02:26:41 +00:00
|
|
|
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;
|
2012-11-08 01:20:48 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = (RegSetValueExA(hApp, key_name, 0, dwType, src, src_size) == ERROR_SUCCESS);
|
|
|
|
|
|
|
|
out:
|
2015-01-23 02:26:41 +00:00
|
|
|
if (hSoftware != NULL)
|
|
|
|
RegCloseKey(hSoftware);
|
|
|
|
if (hApp != NULL)
|
|
|
|
RegCloseKey(hApp);
|
2012-11-08 01:20:48 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helpers for 64 bit registry operations */
|
2013-02-02 16:57:46 +00:00
|
|
|
#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))
|
2012-11-08 01:20:48 +00:00
|
|
|
// Check that a key is accessible for R/W (will create a key if not already existing)
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL CheckRegistryKey64(HKEY root, const char* key) {
|
2012-11-08 01:20:48 +00:00
|
|
|
LONGLONG val;
|
2015-01-25 00:56:38 +00:00
|
|
|
return GetRegistryKey64(root, key, &val);
|
2012-11-08 01:20:48 +00:00
|
|
|
}
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline int64_t ReadRegistryKey64(HKEY root, const char* key) {
|
2012-11-08 01:20:48 +00:00
|
|
|
LONGLONG val;
|
2013-02-02 16:57:46 +00:00
|
|
|
GetRegistryKey64(root, key, &val);
|
2012-11-08 01:20:48 +00:00
|
|
|
return (int64_t)val;
|
|
|
|
}
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL WriteRegistryKey64(HKEY root, const char* key, int64_t val) {
|
2012-11-08 01:20:48 +00:00
|
|
|
LONGLONG tmp = (LONGLONG)val;
|
2013-02-02 16:57:46 +00:00
|
|
|
return SetRegistryKey64(root, key, tmp);
|
2012-11-08 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Helpers for 32 bit registry operations */
|
2013-02-02 16:57:46 +00:00
|
|
|
#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) {
|
2012-11-08 01:20:48 +00:00
|
|
|
DWORD val;
|
2013-02-02 16:57:46 +00:00
|
|
|
return (GetRegistryKey32(root, key, &val) && SetRegistryKey32(root, key, val));
|
2012-11-08 01:20:48 +00:00
|
|
|
}
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline int32_t ReadRegistryKey32(HKEY root, const char* key) {
|
2012-11-08 01:20:48 +00:00
|
|
|
DWORD val;
|
2013-02-02 16:57:46 +00:00
|
|
|
GetRegistryKey32(root, key, &val);
|
2012-11-08 01:20:48 +00:00
|
|
|
return (int32_t)val;
|
|
|
|
}
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline BOOL WriteRegistryKey32(HKEY root, const char* key, int32_t val) {
|
2012-11-08 01:20:48 +00:00
|
|
|
DWORD tmp = (DWORD)val;
|
2013-02-02 16:57:46 +00:00
|
|
|
return SetRegistryKey32(root, key, tmp);
|
2012-11-08 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Helpers for boolean registry operations */
|
2015-01-25 00:56:38 +00:00
|
|
|
#define ReadRegistryKeyBool(root, key) (ReadRegistryKey32(root, key) != 0)
|
|
|
|
#define WriteRegistryKeyBool(root, key, b) WriteRegistryKey32(root, key, (b)?1:0)
|
2012-11-08 01:20:48 +00:00
|
|
|
#define CheckRegistryKeyBool CheckRegistryKey32
|
|
|
|
|
|
|
|
/* Helpers for String registry operations */
|
2013-02-02 16:57:46 +00:00
|
|
|
#define GetRegistryKeyStr(root, key, str, len) _GetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)len)
|
2013-12-22 20:48:57 +00:00
|
|
|
#define SetRegistryKeyStr(root, key, str) _SetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)safe_strlen(str))
|
2012-11-08 01:20:48 +00:00
|
|
|
// Use a static buffer - don't allocate
|
2013-02-02 16:57:46 +00:00
|
|
|
static __inline char* ReadRegistryKeyStr(HKEY root, const char* key) {
|
2012-11-08 01:20:48 +00:00
|
|
|
static char str[512];
|
2013-12-15 21:27:25 +00:00
|
|
|
str[0] = 0;
|
2013-02-02 16:57:46 +00:00
|
|
|
_GetRegistryKey(root, key, REG_SZ, (LPBYTE)str, (DWORD)sizeof(str)-1);
|
2012-11-08 01:20:48 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
#define WriteRegistryKeyStr SetRegistryKeyStr
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|