mirror of
git://source.winehq.org/git/wine.git
synced 2024-08-31 12:44:08 +00:00
687 lines
19 KiB
C
687 lines
19 KiB
C
/*
|
|
* Registry editing UI functions.
|
|
*
|
|
* Copyright (C) 2003 Dimitrie O. Paun
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
|
|
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <commdlg.h>
|
|
#include <cderr.h>
|
|
#include <shellapi.h>
|
|
#include <shlwapi.h>
|
|
|
|
#include "main.h"
|
|
|
|
static BOOL isDecimal;
|
|
|
|
struct edit_params
|
|
{
|
|
HKEY hkey;
|
|
const WCHAR *value_name;
|
|
DWORD type;
|
|
void *data;
|
|
DWORD size;
|
|
};
|
|
|
|
static int vmessagebox(HWND hwnd, int buttons, int titleId, int resId, va_list va_args)
|
|
{
|
|
WCHAR title[256];
|
|
WCHAR fmt[1024];
|
|
WCHAR *str;
|
|
int ret;
|
|
|
|
LoadStringW(hInst, titleId, title, ARRAY_SIZE(title));
|
|
LoadStringW(hInst, resId, fmt, ARRAY_SIZE(fmt));
|
|
|
|
FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
fmt, 0, 0, (WCHAR *)&str, 0, &va_args);
|
|
ret = MessageBoxW(hwnd, str, title, buttons);
|
|
LocalFree(str);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int WINAPIV messagebox(HWND hwnd, int buttons, int titleId, int resId, ...)
|
|
{
|
|
va_list ap;
|
|
INT result;
|
|
|
|
va_start(ap, resId);
|
|
result = vmessagebox(hwnd, buttons, titleId, resId, ap);
|
|
va_end(ap);
|
|
|
|
return result;
|
|
}
|
|
|
|
static void WINAPIV error_code_messagebox(HWND hwnd, unsigned int msg_id, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, msg_id);
|
|
vmessagebox(hwnd, MB_OK|MB_ICONERROR, IDS_ERROR, msg_id, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
static BOOL update_registry_value(HWND hwndDlg, struct edit_params *params)
|
|
{
|
|
HWND hwndValue;
|
|
unsigned int len;
|
|
WCHAR *buf;
|
|
LONG ret;
|
|
|
|
hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
|
|
len = GetWindowTextLengthW(hwndValue);
|
|
buf = malloc((len + 1) * sizeof(WCHAR));
|
|
len = GetWindowTextW(hwndValue, buf, len + 1);
|
|
|
|
free(params->data);
|
|
|
|
switch (params->type)
|
|
{
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
params->data = buf;
|
|
params->size = (len + 1) * sizeof(WCHAR);
|
|
break;
|
|
case REG_DWORD:
|
|
params->size = sizeof(DWORD);
|
|
params->data = malloc(params->size);
|
|
swscanf(buf, isDecimal ? L"%lu" : L"%lx", params->data);
|
|
free(buf);
|
|
break;
|
|
case REG_QWORD:
|
|
params->size = sizeof(UINT64);
|
|
params->data = malloc(params->size);
|
|
swscanf(buf, isDecimal ? L"%I64u" : L"%I64x", params->data);
|
|
free(buf);
|
|
break;
|
|
case REG_MULTI_SZ:
|
|
{
|
|
WCHAR *tmp = malloc((len + 2) * sizeof(WCHAR));
|
|
unsigned int i, j;
|
|
|
|
for (i = 0, j = 0; i < len; i++)
|
|
{
|
|
if (buf[i] == '\r' && buf[i + 1] == '\n')
|
|
{
|
|
if (tmp[j - 1]) tmp[j++] = 0;
|
|
i++;
|
|
}
|
|
else tmp[j++] = buf[i];
|
|
}
|
|
|
|
tmp[j++] = 0;
|
|
tmp[j++] = 0;
|
|
|
|
free(buf);
|
|
params->data = tmp;
|
|
params->size = j * sizeof(WCHAR);
|
|
break;
|
|
}
|
|
default: /* hex data types */
|
|
free(buf);
|
|
params->size = SendMessageW(hwndValue, HEM_GETDATA, 0, 0);
|
|
params->data = malloc(params->size);
|
|
SendMessageW(hwndValue, HEM_GETDATA, (WPARAM)params->size, (LPARAM)params->data);
|
|
}
|
|
|
|
ret = RegSetValueExW(params->hkey, params->value_name, 0, params->type, (BYTE *)params->data, params->size);
|
|
if (ret) error_code_messagebox(hwndDlg, IDS_SET_VALUE_FAILED);
|
|
|
|
return !ret;
|
|
}
|
|
|
|
static void set_dlgproc_value_name(HWND hwndDlg, struct edit_params *params)
|
|
{
|
|
if (params->value_name)
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, params->value_name);
|
|
else
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, g_pszDefaultValueName);
|
|
}
|
|
|
|
static INT_PTR CALLBACK modify_string_dlgproc(HWND hwndDlg, UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
struct edit_params *params;
|
|
int ret = 0;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
params = (struct edit_params *)lparam;
|
|
SetWindowLongPtrW(hwndDlg, DWLP_USER, (ULONG_PTR)params);
|
|
set_dlgproc_value_name(hwndDlg, params);
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, params->data);
|
|
return TRUE;
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wparam))
|
|
{
|
|
case IDOK:
|
|
params = (struct edit_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
|
|
ret = update_registry_value(hwndDlg, params);
|
|
/* fall through */
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, ret);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void set_dword_edit_limit(HWND hwndDlg, DWORD type)
|
|
{
|
|
if (isDecimal)
|
|
SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, EM_SETLIMITTEXT, type == REG_DWORD ? 10 : 20, 0);
|
|
else
|
|
SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, EM_SETLIMITTEXT, type == REG_DWORD ? 8 : 16, 0);
|
|
}
|
|
|
|
static void change_dword_base(HWND hwndDlg, BOOL toHex, DWORD type)
|
|
{
|
|
WCHAR buf[64];
|
|
unsigned int len;
|
|
UINT64 val;
|
|
|
|
len = GetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, buf, ARRAY_SIZE(buf));
|
|
if (!len) SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, L"0");
|
|
|
|
if ((isDecimal && !toHex) || (!isDecimal && toHex))
|
|
return;
|
|
|
|
if (len)
|
|
{
|
|
swscanf(buf, toHex ? L"%I64u" : L"%I64x", &val);
|
|
swprintf(buf, ARRAY_SIZE(buf), toHex ? L"%I64x" : L"%I64u", val);
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, buf);
|
|
}
|
|
|
|
isDecimal = !toHex;
|
|
|
|
set_dword_edit_limit(hwndDlg, type);
|
|
}
|
|
|
|
static INT_PTR CALLBACK modify_dword_dlgproc(HWND hwndDlg, UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
static struct edit_params *params;
|
|
WCHAR buf[64];
|
|
int ret = 0;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
params = (struct edit_params *)lparam;
|
|
SetWindowLongPtrW(hwndDlg, DWLP_USER, (ULONG_PTR)params);
|
|
set_dlgproc_value_name(hwndDlg, params);
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, params->data);
|
|
CheckRadioButton(hwndDlg, IDC_DWORD_HEX, IDC_DWORD_DEC, IDC_DWORD_HEX);
|
|
isDecimal = FALSE;
|
|
if (params->type == REG_QWORD && LoadStringW(GetModuleHandleW(0), IDS_EDIT_QWORD, buf, ARRAY_SIZE(buf)))
|
|
SetWindowTextW(hwndDlg, buf);
|
|
set_dword_edit_limit(hwndDlg, params->type);
|
|
return TRUE;
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wparam))
|
|
{
|
|
case IDC_DWORD_HEX:
|
|
change_dword_base(hwndDlg, TRUE, params->type);
|
|
break;
|
|
case IDC_DWORD_DEC:
|
|
change_dword_base(hwndDlg, FALSE, params->type);
|
|
break;
|
|
case IDOK:
|
|
params = (struct edit_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
|
|
if (!SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, EM_LINELENGTH, 0, 0))
|
|
SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, L"0");
|
|
ret = update_registry_value(hwndDlg, params);
|
|
/* fall through */
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, ret);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
struct edit_params *params;
|
|
int ret = 0;
|
|
|
|
switch(uMsg) {
|
|
case WM_INITDIALOG:
|
|
params = (struct edit_params *)lParam;
|
|
SetWindowLongPtrW(hwndDlg, DWLP_USER, (ULONG_PTR)params);
|
|
set_dlgproc_value_name(hwndDlg, params);
|
|
SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, HEM_SETDATA, (WPARAM)params->size, (LPARAM)params->data);
|
|
SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, WM_SETFONT, (WPARAM) GetStockObject(ANSI_FIXED_FONT), TRUE);
|
|
return TRUE;
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
params = (struct edit_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
|
|
ret = update_registry_value(hwndDlg, params);
|
|
/* fall through */
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, ret);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL read_value(HWND hwnd, struct edit_params *params)
|
|
{
|
|
LONG ret;
|
|
WCHAR *buf = NULL;
|
|
|
|
if ((ret = RegQueryValueExW(params->hkey, params->value_name, NULL, ¶ms->type, NULL, ¶ms->size)))
|
|
{
|
|
if (ret == ERROR_FILE_NOT_FOUND && !params->value_name)
|
|
{
|
|
params->type = REG_SZ;
|
|
params->size = sizeof(WCHAR);
|
|
params->data = malloc(params->size);
|
|
*(WCHAR *)params->data = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
goto error;
|
|
}
|
|
|
|
buf = malloc(params->size + sizeof(WCHAR));
|
|
|
|
if (RegQueryValueExW(params->hkey, params->value_name, NULL, ¶ms->type, (BYTE *)buf, ¶ms->size))
|
|
goto error;
|
|
|
|
if (params->size % sizeof(WCHAR) == 0)
|
|
buf[params->size / sizeof(WCHAR)] = 0;
|
|
|
|
params->data = buf;
|
|
|
|
return TRUE;
|
|
|
|
error:
|
|
error_code_messagebox(hwnd, IDS_BAD_VALUE, params->value_name);
|
|
free(buf);
|
|
params->data = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CreateKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPWSTR keyName)
|
|
{
|
|
BOOL result = FALSE;
|
|
LONG lRet = ERROR_SUCCESS;
|
|
HKEY retKey = NULL;
|
|
WCHAR newKey[MAX_NEW_KEY_LEN - 4];
|
|
int keyNum;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_CREATE_SUB_KEY, &hKey);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_CREATE_KEY_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
if (!LoadStringW(GetModuleHandleW(0), IDS_NEWKEY, newKey, ARRAY_SIZE(newKey))) goto done;
|
|
|
|
/* try to find a name for the key being created (maximum = 100 attempts) */
|
|
for (keyNum = 1; keyNum < 100; keyNum++) {
|
|
wsprintfW(keyName, newKey, keyNum);
|
|
lRet = RegOpenKeyW(hKey, keyName, &retKey);
|
|
if (lRet) break;
|
|
RegCloseKey(retKey);
|
|
}
|
|
if (lRet == ERROR_SUCCESS) goto done;
|
|
|
|
lRet = RegCreateKeyW(hKey, keyName, &retKey);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_CREATE_KEY_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
done:
|
|
RegCloseKey(retKey);
|
|
return result;
|
|
}
|
|
|
|
static void format_dlgproc_string(struct edit_params *params)
|
|
{
|
|
int i, j, count, len;
|
|
WCHAR *str, *buf;
|
|
|
|
if (params->type == REG_DWORD || params->type == REG_QWORD)
|
|
{
|
|
UINT64 value = *((UINT64 *)params->data);
|
|
|
|
params->data = realloc(params->data, 32 * sizeof(WCHAR));
|
|
swprintf(params->data, 32, params->type == REG_DWORD ? L"%lx" : L"%I64x", value);
|
|
return;
|
|
}
|
|
|
|
/* REG_MULTI_SZ */
|
|
len = params->size / sizeof(WCHAR);
|
|
str = params->data;
|
|
|
|
for (i = 0, count = 0; i < len; i++)
|
|
{
|
|
if (!str[i] && str[i + 1]) count++;
|
|
}
|
|
|
|
buf = malloc(params->size + (count * sizeof(WCHAR)));
|
|
|
|
for (i = 0, j = 0; i < len; i++)
|
|
{
|
|
if (!str[i] && str[i + 1])
|
|
{
|
|
buf[j++] = '\r';
|
|
buf[j++] = '\n';
|
|
}
|
|
else buf[j++] = str[i];
|
|
}
|
|
|
|
free(params->data);
|
|
str = NULL;
|
|
params->data = buf;
|
|
}
|
|
|
|
BOOL ModifyValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR valueName)
|
|
{
|
|
struct edit_params params;
|
|
BOOL result = FALSE;
|
|
|
|
if (RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, ¶ms.hkey))
|
|
{
|
|
error_code_messagebox(hwnd, IDS_SET_VALUE_FAILED);
|
|
return FALSE;
|
|
}
|
|
|
|
params.value_name = valueName;
|
|
|
|
if (!read_value(hwnd, ¶ms))
|
|
{
|
|
RegCloseKey(params.hkey);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (params.type)
|
|
{
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
result = DialogBoxParamW(NULL, MAKEINTRESOURCEW(IDD_EDIT_STRING), hwnd,
|
|
modify_string_dlgproc, (LPARAM)¶ms);
|
|
break;
|
|
case REG_DWORD:
|
|
case REG_QWORD:
|
|
format_dlgproc_string(¶ms);
|
|
result = DialogBoxParamW(NULL, MAKEINTRESOURCEW(IDD_EDIT_DWORD), hwnd,
|
|
modify_dword_dlgproc, (LPARAM)¶ms);
|
|
break;
|
|
case REG_MULTI_SZ:
|
|
format_dlgproc_string(¶ms);
|
|
result = DialogBoxParamW(NULL, MAKEINTRESOURCEW(IDD_EDIT_MULTI_STRING), hwnd,
|
|
modify_string_dlgproc, (LPARAM)¶ms);
|
|
break;
|
|
default: /* hex data types */
|
|
result = DialogBoxParamW(NULL, MAKEINTRESOURCEW(IDD_EDIT_BINARY), hwnd,
|
|
modify_binary_dlgproc, (LPARAM)¶ms);
|
|
}
|
|
|
|
/* Update the listview item with the new data string */
|
|
if (result)
|
|
{
|
|
int index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
|
|
MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
|
|
|
|
format_value_data(g_pChildWnd->hListWnd, index, params.type, params.data, params.size);
|
|
}
|
|
|
|
free(params.data);
|
|
RegCloseKey(params.hkey);
|
|
return result;
|
|
}
|
|
|
|
BOOL DeleteKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath)
|
|
{
|
|
BOOL result = FALSE;
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ|KEY_SET_VALUE, &hKey);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_DELETE_KEY_FAILED);
|
|
return FALSE;
|
|
}
|
|
|
|
if (messagebox(hwnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_KEY_TITLE,
|
|
IDS_DELETE_KEY_TEXT) != IDYES)
|
|
goto done;
|
|
|
|
lRet = SHDeleteKeyW(hKeyRoot, keyPath);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_BAD_KEY, keyPath);
|
|
goto done;
|
|
}
|
|
result = TRUE;
|
|
|
|
done:
|
|
RegCloseKey(hKey);
|
|
return result;
|
|
}
|
|
|
|
BOOL DeleteValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR valueName)
|
|
{
|
|
BOOL result = FALSE;
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
|
|
if (lRet) return FALSE;
|
|
|
|
lRet = RegDeleteValueW(hKey, valueName);
|
|
if (lRet && valueName) {
|
|
error_code_messagebox(hwnd, IDS_BAD_VALUE, valueName);
|
|
}
|
|
if (lRet) goto done;
|
|
result = TRUE;
|
|
|
|
done:
|
|
RegCloseKey(hKey);
|
|
return result;
|
|
}
|
|
|
|
BOOL CreateValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, DWORD valueType, LPWSTR valueName)
|
|
{
|
|
LONG lRet = ERROR_SUCCESS;
|
|
WCHAR newValue[256];
|
|
UINT64 value = 0;
|
|
DWORD size_bytes;
|
|
BOOL result = FALSE;
|
|
int valueNum, index;
|
|
HKEY hKey;
|
|
LVITEMW item;
|
|
|
|
lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!LoadStringW(GetModuleHandleW(0), IDS_NEWVALUE, newValue, ARRAY_SIZE(newValue))) goto done;
|
|
|
|
/* try to find a name for the value being created (maximum = 100 attempts) */
|
|
for (valueNum = 1; valueNum < 100; valueNum++) {
|
|
wsprintfW(valueName, newValue, valueNum);
|
|
lRet = RegQueryValueExW(hKey, valueName, 0, 0, 0, 0);
|
|
if (lRet == ERROR_FILE_NOT_FOUND) break;
|
|
}
|
|
if (lRet != ERROR_FILE_NOT_FOUND) {
|
|
error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
switch (valueType)
|
|
{
|
|
case REG_DWORD:
|
|
case REG_DWORD_BIG_ENDIAN:
|
|
size_bytes = sizeof(DWORD);
|
|
break;
|
|
case REG_QWORD:
|
|
size_bytes = sizeof(UINT64);
|
|
break;
|
|
case REG_BINARY:
|
|
size_bytes = 0;
|
|
break;
|
|
case REG_MULTI_SZ:
|
|
size_bytes = 2 * sizeof(WCHAR);
|
|
break;
|
|
default: /* REG_NONE, REG_SZ, REG_EXPAND_SZ */
|
|
size_bytes = sizeof(WCHAR);
|
|
}
|
|
|
|
lRet = RegSetValueExW(hKey, valueName, 0, valueType, (BYTE *)&value, size_bytes);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
/* Add the new item to the listview */
|
|
index = AddEntryToList(g_pChildWnd->hListWnd, valueName, valueType, (BYTE *)&value, size_bytes, -1);
|
|
item.state = LVIS_FOCUSED | LVIS_SELECTED;
|
|
item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
|
|
SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, index, (LPARAM)&item);
|
|
|
|
result = TRUE;
|
|
|
|
done:
|
|
RegCloseKey(hKey);
|
|
return result;
|
|
}
|
|
|
|
BOOL RenameValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR oldName, LPCWSTR newName)
|
|
{
|
|
struct edit_params params;
|
|
BOOL result = FALSE;
|
|
|
|
if (!oldName) return FALSE;
|
|
if (!newName) return FALSE;
|
|
|
|
if (RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, ¶ms.hkey))
|
|
{
|
|
error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RegQueryValueExW(params.hkey, newName, NULL, NULL, NULL, NULL))
|
|
{
|
|
error_code_messagebox(hwnd, IDS_VALUE_EXISTS, oldName);
|
|
goto done;
|
|
}
|
|
|
|
params.value_name = oldName;
|
|
if (!read_value(hwnd, ¶ms)) goto done;
|
|
|
|
if (RegSetValueExW(params.hkey, newName, 0, params.type, (BYTE *)params.data, params.size))
|
|
{
|
|
error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
if (RegDeleteValueW(params.hkey, oldName))
|
|
{
|
|
RegDeleteValueW(params.hkey, newName);
|
|
error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
done:
|
|
free(params.data);
|
|
RegCloseKey(params.hkey);
|
|
return result;
|
|
}
|
|
|
|
BOOL RenameKey(HWND hwnd, HKEY hRootKey, LPCWSTR keyPath, LPCWSTR newName)
|
|
{
|
|
LPWSTR parentPath = 0;
|
|
LPCWSTR srcSubKey = 0;
|
|
HKEY parentKey = 0;
|
|
HKEY destKey = 0;
|
|
BOOL result = FALSE;
|
|
LONG lRet;
|
|
DWORD disposition;
|
|
|
|
if (!keyPath || !newName) return FALSE;
|
|
|
|
if (!wcsrchr(keyPath, '\\')) {
|
|
parentKey = hRootKey;
|
|
srcSubKey = keyPath;
|
|
} else {
|
|
LPWSTR srcSubKey_copy;
|
|
|
|
parentPath = malloc((lstrlenW(keyPath) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(parentPath, keyPath);
|
|
srcSubKey_copy = wcsrchr(parentPath, '\\');
|
|
*srcSubKey_copy = 0;
|
|
srcSubKey = srcSubKey_copy + 1;
|
|
lRet = RegOpenKeyExW(hRootKey, parentPath, 0, KEY_READ | KEY_CREATE_SUB_KEY, &parentKey);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* The following fails if the old name is the same as the new name. */
|
|
if (!lstrcmpW(srcSubKey, newName)) goto done;
|
|
|
|
lRet = RegCreateKeyExW(parentKey, newName, 0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL /* FIXME */, &destKey, &disposition);
|
|
if (disposition == REG_OPENED_EXISTING_KEY)
|
|
lRet = ERROR_FILE_EXISTS;
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_KEY_EXISTS, srcSubKey);
|
|
goto done;
|
|
}
|
|
|
|
/* FIXME: SHCopyKey does not copy the security attributes */
|
|
lRet = SHCopyKeyW(parentKey, srcSubKey, destKey, 0);
|
|
if (lRet) {
|
|
RegCloseKey(destKey);
|
|
RegDeleteKeyW(parentKey, newName);
|
|
error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
lRet = SHDeleteKeyW(hRootKey, keyPath);
|
|
if (lRet) {
|
|
error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
|
|
goto done;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
done:
|
|
RegCloseKey(destKey);
|
|
RegCloseKey(parentKey);
|
|
free(parentPath);
|
|
return result;
|
|
}
|