Streamline the editing interfaces a bit.
[wine/testsucceed.git] / programs / regedit / edit.c
blob0b881a1783d1d691f70673c0e37ac6d9b671f5ae
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(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath)
160 BOOL result = FALSE;
161 LONG lRet = ERROR_SUCCESS;
162 HKEY retKey;
163 TCHAR keyName[32];
164 TCHAR newKey[COUNT_OF(keyName) - 4];
165 int keyNum;
166 HKEY hKey;
168 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_CREATE_SUB_KEY, &hKey);
169 if (lRet != ERROR_SUCCESS) return FALSE;
171 if (!LoadString(GetModuleHandle(0), IDS_NEWKEY, newKey, COUNT_OF(newKey))) goto done;
173 /* try to find out a name for the newly create key (max 100 times) */
174 for (keyNum = 1; keyNum < 100; keyNum++) {
175 wsprintf(keyName, newKey, keyNum);
176 lRet = RegOpenKey(hKey, keyName, &retKey);
177 if (lRet != ERROR_SUCCESS) break;
178 RegCloseKey(retKey);
180 if (lRet == ERROR_SUCCESS) goto done;
182 lRet = RegCreateKey(hKey, keyName, &retKey);
183 if (lRet != ERROR_SUCCESS) goto done;
184 result = TRUE;
186 done:
187 RegCloseKey(retKey);
188 return result;
191 BOOL ModifyValue(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, LPCTSTR valueName)
193 BOOL result = FALSE;
194 DWORD type;
195 LONG lRet;
196 HKEY hKey;
198 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
199 if (lRet != ERROR_SUCCESS) return FALSE;
201 editValueName = valueName;
202 if(!(stringValueData = read_value(hwnd, hKey, valueName, &type, 0))) goto done;
204 if ( (type == REG_SZ) || (type == REG_EXPAND_SZ) ) {
205 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING), hwnd, modify_dlgproc) == IDOK) {
206 lRet = RegSetValueEx(hKey, valueName, 0, type, stringValueData, lstrlen(stringValueData) + 1);
207 if (lRet == ERROR_SUCCESS) result = TRUE;
209 } else if ( type == REG_DWORD ) {
210 wsprintf(stringValueData, isDecimal ? "%ld" : "%lx", *((DWORD*)stringValueData));
211 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dlgproc) == IDOK) {
212 DWORD val;
213 if (_stscanf(stringValueData, isDecimal ? "%ld" : "%lx", &val)) {
214 lRet = RegSetValueEx(hKey, valueName, 0, type, (BYTE*)&val, sizeof(val));
215 if (lRet == ERROR_SUCCESS) result = TRUE;
218 } else {
219 error(hwnd, IDS_UNSUPPORTED_TYPE, type);
222 done:
223 HeapFree(GetProcessHeap(), 0, stringValueData);
224 stringValueData = NULL;
225 RegCloseKey(hKey);
226 return result;
229 BOOL DeleteValue(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, LPCTSTR valueName)
231 BOOL result = FALSE;
232 LONG lRet;
233 HKEY hKey;
235 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_SET_VALUE, &hKey);
236 if (lRet != ERROR_SUCCESS) return FALSE;
238 if (messagebox(hwnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_BOX_TITLE, IDS_DELETE_BOX_TEXT, valueName) != IDYES)
239 goto done;
241 lRet = RegDeleteValue(hKey, valueName);
242 if (lRet != ERROR_SUCCESS) {
243 error(hwnd, IDS_BAD_VALUE, valueName);
245 if (lRet != ERROR_SUCCESS) goto done;
246 result = TRUE;
248 done:
249 RegCloseKey(hKey);
250 return result;
253 BOOL CreateValue(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, DWORD valueType)
255 LONG lRet = ERROR_SUCCESS;
256 TCHAR valueName[32];
257 TCHAR newValue[COUNT_OF(valueName) - 4];
258 DWORD valueDword = 0;
259 BOOL result = FALSE;
260 int valueNum;
261 HKEY hKey;
263 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
264 if (lRet != ERROR_SUCCESS) return FALSE;
266 if (!LoadString(GetModuleHandle(0), IDS_NEWVALUE, newValue, COUNT_OF(newValue))) goto done;
268 /* try to find out a name for the newly create key (max 100 times) */
269 for (valueNum = 1; valueNum < 100; valueNum++) {
270 wsprintf(valueName, newValue, valueNum);
271 lRet = RegQueryValueEx(hKey, valueName, 0, 0, 0, 0);
272 if (lRet != ERROR_SUCCESS) break;
274 if (lRet == ERROR_SUCCESS) goto done;
276 lRet = RegSetValueEx(hKey, valueName, 0, valueType, (BYTE*)&valueDword, sizeof(DWORD));
277 if (lRet != ERROR_SUCCESS) goto done;
278 result = TRUE;
280 done:
281 RegCloseKey(hKey);
282 return result;
285 BOOL RenameValue(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, LPCTSTR oldName, LPCTSTR newName)
287 LPTSTR value = NULL;
288 DWORD type;
289 LONG len, lRet;
290 BOOL result = FALSE;
291 HKEY hKey;
293 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
294 if (lRet != ERROR_SUCCESS) return FALSE;
295 value = read_value(hwnd, hKey, oldName, &type, &len);
296 if(!value) goto done;
297 lRet = RegSetValueEx(hKey, newName, 0, type, (BYTE*)value, len);
298 if (lRet != ERROR_SUCCESS) goto done;
299 lRet = RegDeleteValue(hKey, oldName);
300 if (lRet != ERROR_SUCCESS) {
301 RegDeleteValue(hKey, newName);
302 goto done;
304 result = TRUE;
306 done:
307 HeapFree(GetProcessHeap(), 0, value);
308 RegCloseKey(hKey);
309 return result;