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