ba5e7be464399cc88e5f31a297883857b33faaaf
[reactos.git] / reactos / base / applications / regedit / edit.c
1 /*
2 * Registry editing UI functions.
3 *
4 * Copyright (C) 2003 Dimitrie O. Paun
5 *
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.
10 *
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.
15 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <regedit.h>
22
23 typedef enum _EDIT_MODE
24 {
25 EDIT_MODE_DEC,
26 EDIT_MODE_HEX
27 } EDIT_MODE;
28
29
30 static const TCHAR* editValueName;
31 static TCHAR* stringValueData;
32 static PVOID binValueData;
33 static DWORD dwordValueData;
34 static DWORD valueDataLen;
35 static EDIT_MODE dwordEditMode = EDIT_MODE_HEX;
36
37 void error(HWND hwnd, INT resId, ...)
38 {
39 va_list ap;
40 TCHAR title[256];
41 TCHAR errfmt[1024];
42 TCHAR errstr[1024];
43 HINSTANCE hInstance;
44
45 hInstance = GetModuleHandle(0);
46
47 if (!LoadString(hInstance, IDS_ERROR, title, COUNT_OF(title)))
48 _tcscpy(title, _T("Error"));
49
50 if (!LoadString(hInstance, resId, errfmt, COUNT_OF(errfmt)))
51 _tcscpy(errfmt, _T("Unknown error string!"));
52
53 va_start(ap, resId);
54 _vsntprintf(errstr, COUNT_OF(errstr), errfmt, ap);
55 va_end(ap);
56
57 MessageBox(hwnd, errstr, title, MB_OK | MB_ICONERROR);
58 }
59
60 static void error_code_messagebox(HWND hwnd, DWORD error_code)
61 {
62 TCHAR title[256];
63 if (!LoadString(hInst, IDS_ERROR, title, COUNT_OF(title)))
64 lstrcpy(title, TEXT("Error"));
65 ErrorMessageBox(hwnd, title, error_code);
66 }
67
68 void warning(HWND hwnd, INT resId, ...)
69 {
70 va_list ap;
71 TCHAR title[256];
72 TCHAR errfmt[1024];
73 TCHAR errstr[1024];
74 HINSTANCE hInstance;
75
76 hInstance = GetModuleHandle(0);
77
78 if (!LoadString(hInstance, IDS_WARNING, title, COUNT_OF(title)))
79 _tcscpy(title, _T("Warning"));
80
81 if (!LoadString(hInstance, resId, errfmt, COUNT_OF(errfmt)))
82 _tcscpy(errfmt, _T("Unknown error string!"));
83
84 va_start(ap, resId);
85 _vsntprintf(errstr, COUNT_OF(errstr), errfmt, ap);
86 va_end(ap);
87
88 MessageBox(hwnd, errstr, title, MB_OK | MB_ICONSTOP);
89 }
90
91 INT_PTR CALLBACK modify_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
92 {
93 TCHAR* valueData;
94 HWND hwndValue;
95 int len;
96
97 UNREFERENCED_PARAMETER(lParam);
98
99 switch(uMsg)
100 {
101 case WM_INITDIALOG:
102 if(editValueName && _tcscmp(editValueName, _T("")))
103 {
104 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
105 }
106 else
107 {
108 TCHAR buffer[255];
109 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
110 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
111 }
112 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, stringValueData);
113 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
114 return FALSE;
115 case WM_COMMAND:
116 switch (LOWORD(wParam))
117 {
118 case IDOK:
119 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
120 {
121 if ((len = GetWindowTextLength(hwndValue)))
122 {
123 if (stringValueData)
124 {
125 if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(TCHAR))))
126 {
127 stringValueData = valueData;
128 if (!GetWindowText(hwndValue, stringValueData, len + 1))
129 *stringValueData = 0;
130 }
131 }
132 else
133 {
134 if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR))))
135 {
136 stringValueData = valueData;
137 if (!GetWindowText(hwndValue, stringValueData, len + 1))
138 *stringValueData = 0;
139 }
140 }
141 }
142 else
143 {
144 if (stringValueData)
145 *stringValueData = 0;
146 }
147 }
148 EndDialog(hwndDlg, IDOK);
149 break;
150 case IDCANCEL:
151 EndDialog(hwndDlg, IDCANCEL);
152 return TRUE;
153 }
154 }
155 return FALSE;
156 }
157
158
159 INT_PTR CALLBACK modify_multi_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
160 {
161 TCHAR* valueData;
162 HWND hwndValue;
163 int len;
164
165 UNREFERENCED_PARAMETER(lParam);
166
167 switch(uMsg)
168 {
169 case WM_INITDIALOG:
170 if(editValueName && _tcscmp(editValueName, _T("")))
171 {
172 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
173 }
174 else
175 {
176 TCHAR buffer[255];
177 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
178 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
179 }
180 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, stringValueData);
181 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
182 return FALSE;
183 case WM_COMMAND:
184 switch (LOWORD(wParam))
185 {
186 case IDOK:
187 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
188 {
189 if ((len = GetWindowTextLength(hwndValue)))
190 {
191 if (stringValueData)
192 {
193 if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(TCHAR))))
194 {
195 stringValueData = valueData;
196 if (!GetWindowText(hwndValue, stringValueData, len + 1))
197 *stringValueData = 0;
198 }
199 }
200 else
201 {
202 if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR))))
203 {
204 stringValueData = valueData;
205 if (!GetWindowText(hwndValue, stringValueData, len + 1))
206 *stringValueData = 0;
207 }
208 }
209 }
210 else
211 {
212 if (stringValueData)
213 *stringValueData = 0;
214 }
215 }
216 EndDialog(hwndDlg, IDOK);
217 break;
218 case IDCANCEL:
219 EndDialog(hwndDlg, IDCANCEL);
220 return TRUE;
221 }
222 }
223 return FALSE;
224 }
225
226
227 LRESULT CALLBACK DwordEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
228 {
229 WNDPROC oldwndproc;
230
231 oldwndproc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(hwnd, GWL_USERDATA);
232
233 switch (uMsg)
234 {
235 case WM_CHAR:
236 if (dwordEditMode == EDIT_MODE_DEC)
237 {
238 if (isdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
239 {
240 break;
241 }
242 else
243 {
244 return 0;
245 }
246 }
247 else if (dwordEditMode == EDIT_MODE_HEX)
248 {
249 if (isxdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
250 {
251 break;
252 }
253 else
254 {
255 return 0;
256 }
257 }
258 else
259 {
260 break;
261 }
262 }
263
264 return CallWindowProc(oldwndproc, hwnd, uMsg, wParam, lParam);
265 }
266
267
268 INT_PTR CALLBACK modify_dword_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
269 {
270 WNDPROC oldproc;
271 HWND hwndValue;
272 TCHAR ValueString[32];
273 LPTSTR Remainder;
274 DWORD Base;
275 DWORD Value = 0;
276
277 UNREFERENCED_PARAMETER(lParam);
278
279 switch(uMsg)
280 {
281 case WM_INITDIALOG:
282 dwordEditMode = EDIT_MODE_HEX;
283
284 /* subclass the edit control */
285 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
286 oldproc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(hwndValue, GWL_WNDPROC);
287 SetWindowLongPtr(hwndValue, GWL_USERDATA, (DWORD_PTR)oldproc);
288 SetWindowLongPtr(hwndValue, GWL_WNDPROC, (DWORD_PTR)DwordEditSubclassProc);
289
290 if(editValueName && _tcscmp(editValueName, _T("")))
291 {
292 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
293 }
294 else
295 {
296 TCHAR buffer[255];
297 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
298 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
299 }
300 CheckRadioButton (hwndDlg, IDC_FORMAT_HEX, IDC_FORMAT_DEC, IDC_FORMAT_HEX);
301 _stprintf (ValueString, _T("%lx"), dwordValueData);
302 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
303 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
304 return FALSE;
305
306 case WM_COMMAND:
307 switch (LOWORD(wParam))
308 {
309 case IDC_FORMAT_HEX:
310 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_DEC)
311 {
312 dwordEditMode = EDIT_MODE_HEX;
313 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
314 {
315 if (GetWindowTextLength(hwndValue))
316 {
317 if (GetWindowText(hwndValue, ValueString, 32))
318 {
319 Value = _tcstoul (ValueString, &Remainder, 10);
320 }
321 }
322 }
323 _stprintf (ValueString, _T("%lx"), Value);
324 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
325 return TRUE;
326 }
327 break;
328
329 case IDC_FORMAT_DEC:
330 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_HEX)
331 {
332 dwordEditMode = EDIT_MODE_DEC;
333 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
334 {
335 if (GetWindowTextLength(hwndValue))
336 {
337 if (GetWindowText(hwndValue, ValueString, 32))
338 {
339 Value = _tcstoul (ValueString, &Remainder, 16);
340 }
341 }
342 }
343 _stprintf (ValueString, _T("%lu"), Value);
344 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
345 return TRUE;
346 }
347 break;
348
349 case IDOK:
350 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
351 {
352 if (GetWindowTextLength(hwndValue))
353 {
354 if (!GetWindowText(hwndValue, ValueString, 32))
355 {
356 EndDialog(hwndDlg, IDCANCEL);
357 return TRUE;
358 }
359
360 Base = (dwordEditMode == EDIT_MODE_HEX) ? 16 : 10;
361 dwordValueData = _tcstoul (ValueString, &Remainder, Base);
362 }
363 else
364 {
365 EndDialog(hwndDlg, IDCANCEL);
366 return TRUE;
367 }
368 }
369 EndDialog(hwndDlg, IDOK);
370 return TRUE;
371
372 case IDCANCEL:
373 EndDialog(hwndDlg, IDCANCEL);
374 return TRUE;
375 }
376 }
377 return FALSE;
378 }
379
380
381 INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
382 {
383 HWND hwndValue;
384 UINT len;
385
386 UNREFERENCED_PARAMETER(lParam);
387
388 switch(uMsg)
389 {
390 case WM_INITDIALOG:
391 if(editValueName && _tcscmp(editValueName, _T("")))
392 {
393 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
394 }
395 else
396 {
397 TCHAR buffer[255];
398 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
399 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
400 }
401 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
402 HexEdit_LoadBuffer(hwndValue, binValueData, valueDataLen);
403 /* reset the hex edit control's font */
404 SendMessage(hwndValue, WM_SETFONT, 0, 0);
405 SetFocus(hwndValue);
406 return FALSE;
407 case WM_COMMAND:
408 switch (LOWORD(wParam))
409 {
410 case IDOK:
411 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
412 {
413 len = (UINT) HexEdit_GetBufferSize(hwndValue);
414 if (len > 0 && binValueData)
415 binValueData = HeapReAlloc(GetProcessHeap(), 0, binValueData, len);
416 else
417 binValueData = HeapAlloc(GetProcessHeap(), 0, len + 1);
418 HexEdit_CopyBuffer(hwndValue, binValueData, len);
419 valueDataLen = len;
420 }
421 EndDialog(hwndDlg, IDOK);
422 break;
423 case IDCANCEL:
424 EndDialog(hwndDlg, IDCANCEL);
425 return TRUE;
426 }
427 }
428 return FALSE;
429 }
430
431
432 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCTSTR valueName, BOOL EditBin)
433 {
434 DWORD type;
435 LONG lRet;
436 BOOL result = FALSE;
437
438 if (!hKey)
439 return FALSE;
440
441 editValueName = valueName;
442
443 lRet = RegQueryValueEx(hKey, valueName, 0, &type, 0, &valueDataLen);
444 if (lRet != ERROR_SUCCESS && (!_tcscmp(valueName, _T("")) || valueName == NULL))
445 {
446 lRet = ERROR_SUCCESS; /* Allow editing of (Default) values which don't exist */
447 type = REG_SZ;
448 valueDataLen = 0;
449 stringValueData = NULL;
450 binValueData = NULL;
451 }
452
453 if (lRet != ERROR_SUCCESS)
454 {
455 error(hwnd, IDS_BAD_VALUE, valueName);
456 goto done;
457 }
458
459 if (EditBin == FALSE && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
460 {
461 if (valueDataLen > 0)
462 {
463 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
464 {
465 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
466 goto done;
467 }
468 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
469 if (lRet != ERROR_SUCCESS)
470 {
471 error(hwnd, IDS_BAD_VALUE, valueName);
472 goto done;
473 }
474 }
475 else
476 {
477 stringValueData = NULL;
478 }
479
480 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING), hwnd, modify_string_dlgproc) == IDOK)
481 {
482 if (stringValueData)
483 {
484 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)stringValueData, (DWORD) (_tcslen(stringValueData) + 1) * sizeof(TCHAR));
485 }
486 else
487 {
488 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
489 }
490 if (lRet == ERROR_SUCCESS)
491 result = TRUE;
492 }
493 }
494 else if (EditBin == FALSE && type == REG_MULTI_SZ)
495 {
496 if (valueDataLen > 0)
497 {
498 size_t llen, listlen, nl_len;
499 LPTSTR src, lines = NULL;
500
501 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
502 {
503 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
504 goto done;
505 }
506 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
507 if (lRet != ERROR_SUCCESS)
508 {
509 error(hwnd, IDS_BAD_VALUE, valueName);
510 goto done;
511 }
512
513 /* convert \0 to \r\n */
514 src = stringValueData;
515 nl_len = _tcslen(_T("\r\n")) * sizeof(TCHAR);
516 listlen = sizeof(TCHAR);
517 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listlen + sizeof(TCHAR));
518 while(*src != _T('\0'))
519 {
520 llen = _tcslen(src);
521 if(llen == 0)
522 break;
523 listlen += (llen * sizeof(TCHAR)) + nl_len;
524 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, listlen);
525 _tcscat(lines, src);
526 _tcscat(lines, _T("\r\n"));
527 src += llen + 1;
528 }
529 HeapFree(GetProcessHeap(), 0, stringValueData);
530 stringValueData = lines;
531 }
532 else
533 {
534 stringValueData = NULL;
535 }
536
537 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_MULTI_STRING), hwnd, modify_multi_string_dlgproc) == IDOK)
538 {
539 if (stringValueData)
540 {
541 /* convert \r\n to \0 */
542 BOOL EmptyLines = FALSE;
543 LPTSTR src, lines, nl;
544 size_t linechars, buflen, c_nl, dest;
545
546 src = stringValueData;
547 buflen = sizeof(TCHAR);
548 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(TCHAR));
549 c_nl = _tcslen(_T("\r\n"));
550 dest = 0;
551 while(*src != _T('\0'))
552 {
553 if((nl = _tcsstr(src, _T("\r\n"))))
554 {
555 linechars = nl - src;
556 if(nl == src)
557 {
558 EmptyLines = TRUE;
559 src = nl + c_nl;
560 continue;
561 }
562 }
563 else
564 {
565 linechars = _tcslen(src);
566 }
567 if(linechars > 0)
568 {
569 buflen += ((linechars + 1) * sizeof(TCHAR));
570 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, buflen);
571 memcpy((lines + dest), src, linechars * sizeof(TCHAR));
572 dest += linechars;
573 lines[dest++] = _T('\0');
574 }
575 else
576 {
577 EmptyLines = TRUE;
578 }
579 src += linechars + (nl != NULL ? c_nl : 0);
580 }
581 lines[++dest] = _T('\0');
582
583 if(EmptyLines)
584 {
585 warning(hwnd, IDS_MULTI_SZ_EMPTY_STRING);
586 }
587
588 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)lines, (DWORD) buflen);
589 HeapFree(GetProcessHeap(), 0, lines);
590 }
591 else
592 {
593 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
594 }
595 if (lRet == ERROR_SUCCESS)
596 result = TRUE;
597 }
598 }
599 else if (EditBin == FALSE && type == REG_DWORD)
600 {
601 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)&dwordValueData, &valueDataLen);
602 if (lRet != ERROR_SUCCESS)
603 {
604 error(hwnd, IDS_BAD_VALUE, valueName);
605 goto done;
606 }
607
608 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dword_dlgproc) == IDOK)
609 {
610 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)&dwordValueData, sizeof(DWORD));
611 if (lRet == ERROR_SUCCESS)
612 result = TRUE;
613 }
614 }
615 else if (EditBin == TRUE || type == REG_NONE || type == REG_BINARY)
616 {
617 #ifndef UNICODE
618 LPWSTR u_valuename;
619 int len_vname = lstrlen(valueName);
620
621 if(len_vname > 0)
622 {
623 if(!(u_valuename = HeapAlloc(GetProcessHeap(), 0, (len_vname + 1) * sizeof(WCHAR))))
624 {
625 error(hwnd, IDS_TOO_BIG_VALUE, len_vname);
626 goto done;
627 }
628 /* convert the ansi value name to an unicode string */
629 MultiByteToWideChar(CP_ACP, 0, valueName, -1, u_valuename, len_vname + 1);
630 valueDataLen *= sizeof(WCHAR);
631 }
632 else
633 u_valuename = L"";
634 #endif
635 if(valueDataLen > 0)
636 {
637 if(!(binValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + 1)))
638 {
639 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
640 goto done;
641 }
642
643 /* force to use the unicode version, so editing strings in binary mode is correct */
644 lRet = RegQueryValueExW(hKey,
645 #ifndef UNICODE
646 u_valuename,
647 #else
648 valueName,
649 #endif
650 0, 0, (LPBYTE)binValueData, &valueDataLen);
651 if (lRet != ERROR_SUCCESS)
652 {
653 HeapFree(GetProcessHeap(), 0, binValueData);
654 #ifndef UNICODE
655 if(len_vname > 0)
656 HeapFree(GetProcessHeap(), 0, u_valuename);
657 #endif
658 error(hwnd, IDS_BAD_VALUE, valueName);
659 goto done;
660 }
661 }
662 else
663 {
664 binValueData = NULL;
665 }
666
667 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_BIN_DATA), hwnd, modify_binary_dlgproc) == IDOK)
668 {
669 /* force to use the unicode version, so editing strings in binary mode is correct */
670 lRet = RegSetValueExW(hKey,
671 #ifndef UNICODE
672 u_valuename,
673 #else
674 valueName,
675 #endif
676 0, type, (LPBYTE)binValueData, valueDataLen);
677 if (lRet == ERROR_SUCCESS)
678 result = TRUE;
679 }
680 if(binValueData != NULL)
681 HeapFree(GetProcessHeap(), 0, binValueData);
682 #ifndef UNICODE
683 if(len_vname > 0)
684 HeapFree(GetProcessHeap(), 0, u_valuename);
685 #endif
686 }
687 else
688 {
689 error(hwnd, IDS_UNSUPPORTED_TYPE, type);
690 }
691
692 done:
693 if (stringValueData)
694 HeapFree(GetProcessHeap(), 0, stringValueData);
695 stringValueData = NULL;
696
697 return result;
698 }
699
700 static LONG CopyKey(HKEY hDestKey, LPCTSTR lpDestSubKey, HKEY hSrcKey, LPCTSTR lpSrcSubKey)
701 {
702 LONG lResult;
703 DWORD dwDisposition;
704 HKEY hDestSubKey = NULL;
705 HKEY hSrcSubKey = NULL;
706 DWORD dwIndex, dwType, cbName, cbData;
707 TCHAR szSubKey[256];
708 TCHAR szValueName[256];
709 BYTE szValueData[512];
710
711 FILETIME ft;
712
713 /* open the source subkey, if specified */
714 if (lpSrcSubKey)
715 {
716 lResult = RegOpenKeyEx(hSrcKey, lpSrcSubKey, 0, KEY_ALL_ACCESS, &hSrcSubKey);
717 if (lResult)
718 goto done;
719 hSrcKey = hSrcSubKey;
720 }
721
722 /* create the destination subkey */
723 lResult = RegCreateKeyEx(hDestKey, lpDestSubKey, 0, NULL, 0, KEY_WRITE, NULL,
724 &hDestSubKey, &dwDisposition);
725 if (lResult)
726 goto done;
727
728 /* copy all subkeys */
729 dwIndex = 0;
730 do
731 {
732 cbName = sizeof(szSubKey) / sizeof(szSubKey[0]);
733 lResult = RegEnumKeyEx(hSrcKey, dwIndex++, szSubKey, &cbName, NULL, NULL, NULL, &ft);
734 if (lResult == ERROR_SUCCESS)
735 {
736 lResult = CopyKey(hDestSubKey, szSubKey, hSrcKey, szSubKey);
737 if (lResult)
738 goto done;
739 }
740 }
741 while(lResult == ERROR_SUCCESS);
742
743 /* copy all subvalues */
744 dwIndex = 0;
745 do
746 {
747 cbName = sizeof(szValueName) / sizeof(szValueName[0]);
748 cbData = sizeof(szValueData) / sizeof(szValueData[0]);
749 lResult = RegEnumValue(hSrcKey, dwIndex++, szValueName, &cbName, NULL, &dwType, szValueData, &cbData);
750 if (lResult == ERROR_SUCCESS)
751 {
752 lResult = RegSetValueEx(hDestSubKey, szValueName, 0, dwType, szValueData, cbData);
753 if (lResult)
754 goto done;
755 }
756 }
757 while(lResult == ERROR_SUCCESS);
758
759 lResult = ERROR_SUCCESS;
760
761 done:
762 if (hSrcSubKey)
763 RegCloseKey(hSrcSubKey);
764 if (hDestSubKey)
765 RegCloseKey(hDestSubKey);
766 if (lResult != ERROR_SUCCESS)
767 SHDeleteKey(hDestKey, lpDestSubKey);
768 return lResult;
769 }
770
771 static LONG MoveKey(HKEY hDestKey, LPCTSTR lpDestSubKey, HKEY hSrcKey, LPCTSTR lpSrcSubKey)
772 {
773 LONG lResult;
774
775 if (!lpSrcSubKey)
776 return ERROR_INVALID_FUNCTION;
777
778 lResult = CopyKey(hDestKey, lpDestSubKey, hSrcKey, lpSrcSubKey);
779 if (lResult == ERROR_SUCCESS)
780 SHDeleteKey(hSrcKey, lpSrcSubKey);
781
782 return lResult;
783 }
784
785 BOOL DeleteKey(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath)
786 {
787 TCHAR msg[128], caption[128];
788 BOOL result = FALSE;
789 LONG lRet;
790 HKEY hKey;
791
792 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, KEY_READ|KEY_SET_VALUE, &hKey);
793 if (lRet != ERROR_SUCCESS)
794 {
795 error_code_messagebox(hwnd, lRet);
796 return FALSE;
797 }
798
799 LoadString(hInst, IDS_QUERY_DELETE_KEY_CONFIRM, caption, sizeof(caption)/sizeof(TCHAR));
800 LoadString(hInst, IDS_QUERY_DELETE_KEY_ONE, msg, sizeof(msg)/sizeof(TCHAR));
801
802 if (MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) != IDYES)
803 goto done;
804
805 lRet = SHDeleteKey(hKeyRoot, keyPath);
806 if (lRet != ERROR_SUCCESS)
807 {
808 error(hwnd, IDS_BAD_KEY, keyPath);
809 goto done;
810 }
811 result = TRUE;
812
813 done:
814 RegCloseKey(hKey);
815 return result;
816 }
817
818 LONG RenameKey(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpNewName)
819 {
820 LPCTSTR s;
821 LPTSTR lpNewSubKey = NULL;
822 LONG Ret = 0;
823
824 if (!lpSubKey)
825 return Ret;
826
827 s = _tcsrchr(lpSubKey, _T('\\'));
828 if (s)
829 {
830 s++;
831 lpNewSubKey = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (s - lpSubKey + _tcslen(lpNewName) + 1) * sizeof(TCHAR));
832 if (lpNewSubKey != NULL)
833 {
834 memcpy(lpNewSubKey, lpSubKey, (s - lpSubKey) * sizeof(TCHAR));
835 lstrcpy(lpNewSubKey + (s - lpSubKey), lpNewName);
836 lpNewName = lpNewSubKey;
837 }
838 else
839 return ERROR_NOT_ENOUGH_MEMORY;
840 }
841
842 Ret = MoveKey(hKey, lpNewName, hKey, lpSubKey);
843
844 if (lpNewSubKey)
845 {
846 HeapFree(GetProcessHeap(), 0, lpNewSubKey);
847 }
848 return Ret;
849 }
850
851 LONG RenameValue(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpDestValue, LPCTSTR lpSrcValue)
852 {
853 LONG lResult;
854 HKEY hSubKey = NULL;
855 DWORD dwType, cbData;
856 BYTE data[512];
857
858 if (lpSubKey)
859 {
860 lResult = RegOpenKey(hKey, lpSubKey, &hSubKey);
861 if (lResult != ERROR_SUCCESS)
862 goto done;
863 hKey = hSubKey;
864 }
865
866 cbData = sizeof(data);
867 lResult = RegQueryValueEx(hKey, lpSrcValue, NULL, &dwType, data, &cbData);
868 if (lResult != ERROR_SUCCESS)
869 goto done;
870
871 lResult = RegSetValueEx(hKey, lpDestValue, 0, dwType, data, cbData);
872 if (lResult != ERROR_SUCCESS)
873 goto done;
874
875 RegDeleteValue(hKey, lpSrcValue);
876
877 done:
878 if (hSubKey)
879 RegCloseKey(hSubKey);
880 return lResult;
881 }
882
883 LONG QueryStringValue(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPTSTR pszBuffer, DWORD dwBufferLen)
884 {
885 LONG lResult;
886 HKEY hSubKey = NULL;
887 DWORD cbData, dwType;
888
889 if (lpSubKey)
890 {
891 lResult = RegOpenKey(hKey, lpSubKey, &hSubKey);
892 if (lResult != ERROR_SUCCESS)
893 goto done;
894 hKey = hSubKey;
895 }
896
897 cbData = (dwBufferLen - 1) * sizeof(*pszBuffer);
898 lResult = RegQueryValueEx(hKey, lpValueName, NULL, &dwType, (LPBYTE) pszBuffer, &cbData);
899 if (lResult != ERROR_SUCCESS)
900 goto done;
901 if (dwType != REG_SZ)
902 {
903 lResult = -1;
904 goto done;
905 }
906
907 pszBuffer[cbData / sizeof(*pszBuffer)] = _T('\0');
908
909 done:
910 if (lResult != ERROR_SUCCESS)
911 pszBuffer[0] = _T('\0');
912 if (hSubKey)
913 RegCloseKey(hSubKey);
914 return lResult;
915 }
916
917 BOOL GetKeyName(LPTSTR pszDest, size_t iDestLength, HKEY hRootKey, LPCTSTR lpSubKey)
918 {
919 LPCTSTR pszRootKey;
920
921 if (hRootKey == HKEY_CLASSES_ROOT)
922 pszRootKey = TEXT("HKEY_CLASSES_ROOT");
923 else if (hRootKey == HKEY_CURRENT_USER)
924 pszRootKey = TEXT("HKEY_CURRENT_USER");
925 else if (hRootKey == HKEY_LOCAL_MACHINE)
926 pszRootKey = TEXT("HKEY_LOCAL_MACHINE");
927 else if (hRootKey == HKEY_USERS)
928 pszRootKey = TEXT("HKEY_USERS");
929 else if (hRootKey == HKEY_CURRENT_CONFIG)
930 pszRootKey = TEXT("HKEY_CURRENT_CONFIG");
931 else if (hRootKey == HKEY_DYN_DATA)
932 pszRootKey = TEXT("HKEY_DYN_DATA");
933 else
934 return FALSE;
935
936 if (lpSubKey[0])
937 _sntprintf(pszDest, iDestLength, TEXT("%s\\%s"), pszRootKey, lpSubKey);
938 else
939 _sntprintf(pszDest, iDestLength, TEXT("%s"), pszRootKey);
940 return TRUE;
941 }