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