Add value rename support to regedit.
[wine/dcerpc.git] / programs / regedit / edit.c
blob93c56e0fb3aa8d5870b6e94faa3496f9ac561eac
1 /*
2 * Registry editing UI functions.
4 * Copyright (C) 2003 Dimitrie O. Paun
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
23 #include <windows.h>
24 #include <tchar.h>
25 #include <commctrl.h>
26 #include <commdlg.h>
27 #include <cderr.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <shellapi.h>
32 #include "main.h"
33 #include "regproc.h"
34 #include "resource.h"
36 static const TCHAR* editValueName;
37 static TCHAR* stringValueData;
38 static BOOL isDecimal;
40 INT vmessagebox(HWND hwnd, INT buttons, INT titleId, INT resId, va_list ap)
42 TCHAR title[256];
43 TCHAR errfmt[1024];
44 TCHAR errstr[1024];
46 if (!LoadString(hInst, titleId, title, COUNT_OF(title)))
47 lstrcpy(title, "Error");
49 if (!LoadString(hInst, resId, errfmt, COUNT_OF(errfmt)))
50 lstrcpy(errfmt, "Unknown error string!");
52 _vsntprintf(errstr, COUNT_OF(errstr), errfmt, ap);
54 return MessageBox(hwnd, errstr, title, buttons);
57 INT messagebox(HWND hwnd, INT buttons, INT titleId, INT resId, ...)
59 va_list ap;
60 INT result;
62 va_start(ap, resId);
63 result = vmessagebox(hwnd, buttons, titleId, resId, ap);
64 va_end(ap);
66 return result;
69 void error(HWND hwnd, INT resId, ...)
71 va_list ap;
73 va_start(ap, resId);
74 vmessagebox(hwnd, MB_OK | MB_ICONERROR, IDS_ERROR, resId, ap);
75 va_end(ap);
78 BOOL change_dword_base(HWND hwndDlg, BOOL toHex)
80 TCHAR buf[128];
81 DWORD val;
83 if (!GetDlgItemText(hwndDlg, IDC_VALUE_DATA, buf, COUNT_OF(buf))) return FALSE;
84 if (!_stscanf(buf, toHex ? "%ld" : "%lx", &val)) return FALSE;
85 wsprintf(buf, toHex ? "%lx" : "%ld", val);
86 return SetDlgItemText(hwndDlg, IDC_VALUE_DATA, buf);
89 INT_PTR CALLBACK modify_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
91 TCHAR* valueData;
92 HWND hwndValue;
93 int len;
95 switch(uMsg) {
96 case WM_INITDIALOG:
97 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
98 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, stringValueData);
99 CheckRadioButton(hwndDlg, IDC_DWORD_HEX, IDC_DWORD_DEC, isDecimal ? IDC_DWORD_DEC : IDC_DWORD_HEX);
100 return TRUE;
101 case WM_COMMAND:
102 switch (LOWORD(wParam)) {
103 case IDC_DWORD_HEX:
104 if (isDecimal && change_dword_base(hwndDlg, TRUE)) isDecimal = FALSE;
105 break;
106 case IDC_DWORD_DEC:
107 if (!isDecimal && change_dword_base(hwndDlg, FALSE)) isDecimal = TRUE;
108 break;
109 case IDOK:
110 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA))) {
111 if ((len = GetWindowTextLength(hwndValue))) {
112 if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(TCHAR)))) {
113 stringValueData = valueData;
114 if (!GetWindowText(hwndValue, stringValueData, len + 1))
115 *stringValueData = 0;
119 /* Fall through */
120 case IDCANCEL:
121 EndDialog(hwndDlg, wParam);
122 return TRUE;
125 return FALSE;
128 static LPTSTR read_value(HWND hwnd, HKEY hKey, LPCTSTR valueName, DWORD *lpType, LONG *len)
130 DWORD valueDataLen;
131 LPTSTR buffer = NULL;
132 LONG lRet;
134 lRet = RegQueryValueEx(hKey, valueName, 0, lpType, 0, &valueDataLen);
135 if (lRet != ERROR_SUCCESS) {
136 error(hwnd, IDS_BAD_VALUE, valueName);
137 goto done;
139 if ( *lpType == REG_DWORD ) valueDataLen = sizeof(DWORD);
140 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, valueDataLen))) {
141 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
142 goto done;
144 lRet = RegQueryValueEx(hKey, valueName, 0, 0, buffer, &valueDataLen);
145 if (lRet != ERROR_SUCCESS) {
146 error(hwnd, IDS_BAD_VALUE, valueName);
147 goto done;
150 if(len) *len = valueDataLen;
151 return buffer;
153 done:
154 HeapFree(GetProcessHeap(), 0, buffer);
155 return NULL;
158 BOOL CreateKey(HKEY hKey)
160 LONG lRet = ERROR_SUCCESS;
161 HKEY retKey;
162 TCHAR keyName[32];
163 TCHAR newKey[COUNT_OF(keyName) - 4];
164 int keyNum;
166 /* If we have illegal parameter return with operation failure */
167 if (!hKey) return FALSE;
169 if (!LoadString(GetModuleHandle(0), IDS_NEWKEY, newKey, COUNT_OF(newKey))) return FALSE;
171 /* try to find out a name for the newly create key (max 100 times) */
172 for (keyNum = 1; keyNum < 100; keyNum++) {
173 wsprintf(keyName, newKey, keyNum);
174 lRet = RegOpenKey(hKey, keyName, &retKey);
175 if (lRet != ERROR_SUCCESS) break;
176 RegCloseKey(retKey);
178 if (lRet == ERROR_SUCCESS) return FALSE;
180 lRet = RegCreateKey(hKey, keyName, &retKey);
181 if (lRet != ERROR_SUCCESS) return FALSE;
183 RegCloseKey(retKey);
184 return TRUE;
187 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCTSTR valueName)
189 DWORD type;
190 LONG lRet;
191 BOOL result = FALSE;
193 if (!hKey || !valueName) return FALSE;
195 editValueName = valueName;
196 if(!(stringValueData = read_value(hwnd, hKey, valueName, &type, 0))) goto done;
198 if ( (type == REG_SZ) || (type == REG_EXPAND_SZ) ) {
199 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING), hwnd, modify_dlgproc) == IDOK) {
200 lRet = RegSetValueEx(hKey, valueName, 0, type, stringValueData, lstrlen(stringValueData) + 1);
201 if (lRet == ERROR_SUCCESS) result = TRUE;
203 } else if ( type == REG_DWORD ) {
204 wsprintf(stringValueData, isDecimal ? "%ld" : "%lx", *((DWORD*)stringValueData));
205 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dlgproc) == IDOK) {
206 DWORD val;
207 if (_stscanf(stringValueData, isDecimal ? "%ld" : "%lx", &val)) {
208 lRet = RegSetValueEx(hKey, valueName, 0, type, (BYTE*)&val, sizeof(val));
209 if (lRet == ERROR_SUCCESS) result = TRUE;
212 } else {
213 error(hwnd, IDS_UNSUPPORTED_TYPE, type);
216 done:
217 HeapFree(GetProcessHeap(), 0, stringValueData);
218 stringValueData = NULL;
220 return result;
223 BOOL DeleteValue(HWND hwnd, HKEY hKey, LPCTSTR valueName)
225 LONG lRet;
227 if (!hKey || !valueName) return FALSE;
229 if (messagebox(hwnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_BOX_TITLE, IDS_DELETE_BOX_TEXT, valueName) != IDYES)
230 return FALSE;
232 lRet = RegDeleteValue(hKey, valueName);
233 if (lRet != ERROR_SUCCESS) {
234 error(hwnd, IDS_BAD_VALUE, valueName);
236 return lRet == ERROR_SUCCESS;
239 BOOL CreateValue(HWND hwnd, HKEY hKey, DWORD valueType)
241 LONG lRet = ERROR_SUCCESS;
242 TCHAR valueName[32];
243 TCHAR newValue[COUNT_OF(valueName) - 4];
244 DWORD valueDword = 0;
245 int valueNum;
247 /* If we have illegal parameter return with operation failure */
248 if (!hKey) return FALSE;
250 if (!LoadString(GetModuleHandle(0), IDS_NEWVALUE, newValue, COUNT_OF(newValue))) return FALSE;
252 /* try to find out a name for the newly create key (max 100 times) */
253 for (valueNum = 1; valueNum < 100; valueNum++) {
254 wsprintf(valueName, newValue, valueNum);
255 lRet = RegQueryValueEx(hKey, valueName, 0, 0, 0, 0);
256 if (lRet != ERROR_SUCCESS) break;
258 if (lRet == ERROR_SUCCESS) return FALSE;
260 lRet = RegSetValueEx(hKey, valueName, 0, valueType, (BYTE*)&valueDword, sizeof(DWORD));
261 if (lRet != ERROR_SUCCESS) return FALSE;
263 return TRUE;
266 BOOL RenameValue(HWND hwnd, HKEY hRootKey, LPCTSTR keyPath, LPCTSTR oldName, LPCTSTR newName)
268 LPTSTR value = NULL;
269 DWORD type;
270 LONG len, lRet;
271 BOOL result = FALSE;
272 HKEY hKey;
274 lRet = RegOpenKeyEx(hRootKey, keyPath, 0, KEY_ALL_ACCESS, &hKey);
275 if (lRet != ERROR_SUCCESS) goto done;
276 value = read_value(hwnd, hKey, oldName, &type, &len);
277 if(!value) goto done;
278 lRet = RegSetValueEx(hKey, newName, 0, type, (BYTE*)value, len);
279 if (lRet != ERROR_SUCCESS) goto done;
280 lRet = RegDeleteValue(hKey, oldName);
281 if (lRet != ERROR_SUCCESS) {
282 RegDeleteValue(hKey, newName);
283 goto done;
285 result = TRUE;
287 done:
288 HeapFree(GetProcessHeap(), 0, value);
289 return result;