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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 typedef enum _EDIT_MODE
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
;
37 void error(HWND hwnd
, INT resId
, ...)
45 hInstance
= GetModuleHandle(0);
47 if (!LoadString(hInstance
, IDS_ERROR
, title
, COUNT_OF(title
)))
48 _tcscpy(title
, _T("Error"));
50 if (!LoadString(hInstance
, resId
, errfmt
, COUNT_OF(errfmt
)))
51 _tcscpy(errfmt
, _T("Unknown error string!"));
54 _vsntprintf(errstr
, COUNT_OF(errstr
), errfmt
, ap
);
57 MessageBox(hwnd
, errstr
, title
, MB_OK
| MB_ICONERROR
);
60 static void error_code_messagebox(HWND hwnd
, DWORD error_code
)
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
);
71 lpMsgBuf
= (LPTSTR
)fallback
;
72 MessageBox(hwnd
, lpMsgBuf
, title
, MB_OK
| MB_ICONERROR
);
73 if (lpMsgBuf
!= fallback
)
77 void warning(HWND hwnd
, INT resId
, ...)
85 hInstance
= GetModuleHandle(0);
87 if (!LoadString(hInstance
, IDS_WARNING
, title
, COUNT_OF(title
)))
88 _tcscpy(title
, _T("Warning"));
90 if (!LoadString(hInstance
, resId
, errfmt
, COUNT_OF(errfmt
)))
91 _tcscpy(errfmt
, _T("Unknown error string!"));
94 _vsntprintf(errstr
, COUNT_OF(errstr
), errfmt
, ap
);
97 MessageBox(hwnd
, errstr
, title
, MB_OK
| MB_ICONSTOP
);
100 INT_PTR CALLBACK
modify_string_dlgproc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
106 UNREFERENCED_PARAMETER(lParam
);
110 if(editValueName
&& _tcscmp(editValueName
, _T("")))
112 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, editValueName
);
117 LoadString(hInst
, IDS_DEFAULT_VALUE_NAME
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
118 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, buffer
);
120 SetDlgItemText(hwndDlg
, IDC_VALUE_DATA
, stringValueData
);
121 SetFocus(GetDlgItem(hwndDlg
, IDC_VALUE_DATA
));
124 switch (LOWORD(wParam
))
127 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
129 if ((len
= GetWindowTextLength(hwndValue
)))
133 if ((valueData
= HeapReAlloc(GetProcessHeap(), 0, stringValueData
, (len
+ 1) * sizeof(TCHAR
))))
135 stringValueData
= valueData
;
136 if (!GetWindowText(hwndValue
, stringValueData
, len
+ 1))
137 *stringValueData
= 0;
142 if ((valueData
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(TCHAR
))))
144 stringValueData
= valueData
;
145 if (!GetWindowText(hwndValue
, stringValueData
, len
+ 1))
146 *stringValueData
= 0;
153 *stringValueData
= 0;
156 EndDialog(hwndDlg
, IDOK
);
159 EndDialog(hwndDlg
, IDCANCEL
);
167 INT_PTR CALLBACK
modify_multi_string_dlgproc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
173 UNREFERENCED_PARAMETER(lParam
);
177 if(editValueName
&& _tcscmp(editValueName
, _T("")))
179 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, editValueName
);
184 LoadString(hInst
, IDS_DEFAULT_VALUE_NAME
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
185 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, buffer
);
187 SetDlgItemText(hwndDlg
, IDC_VALUE_DATA
, stringValueData
);
188 SetFocus(GetDlgItem(hwndDlg
, IDC_VALUE_DATA
));
191 switch (LOWORD(wParam
))
194 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
196 if ((len
= GetWindowTextLength(hwndValue
)))
200 if ((valueData
= HeapReAlloc(GetProcessHeap(), 0, stringValueData
, (len
+ 1) * sizeof(TCHAR
))))
202 stringValueData
= valueData
;
203 if (!GetWindowText(hwndValue
, stringValueData
, len
+ 1))
204 *stringValueData
= 0;
209 if ((valueData
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(TCHAR
))))
211 stringValueData
= valueData
;
212 if (!GetWindowText(hwndValue
, stringValueData
, len
+ 1))
213 *stringValueData
= 0;
220 *stringValueData
= 0;
223 EndDialog(hwndDlg
, IDOK
);
226 EndDialog(hwndDlg
, IDCANCEL
);
234 LRESULT CALLBACK
DwordEditSubclassProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
238 oldwndproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(hwnd
, GWL_USERDATA
);
243 if (dwordEditMode
== EDIT_MODE_DEC
)
245 if (isdigit((int) wParam
& 0xff) || iscntrl((int) wParam
& 0xff))
254 else if (dwordEditMode
== EDIT_MODE_HEX
)
256 if (isxdigit((int) wParam
& 0xff) || iscntrl((int) wParam
& 0xff))
271 return CallWindowProc(oldwndproc
, hwnd
, uMsg
, wParam
, lParam
);
275 INT_PTR CALLBACK
modify_dword_dlgproc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
280 TCHAR ValueString
[32];
285 UNREFERENCED_PARAMETER(lParam
);
289 dwordEditMode
= EDIT_MODE_HEX
;
291 /* subclass the edit control */
292 hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
);
293 oldproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(hwndValue
, GWL_WNDPROC
);
294 SetWindowLongPtr(hwndValue
, GWL_USERDATA
, (DWORD_PTR
)oldproc
);
295 SetWindowLongPtr(hwndValue
, GWL_WNDPROC
, (DWORD_PTR
)DwordEditSubclassProc
);
297 if(editValueName
&& _tcscmp(editValueName
, _T("")))
299 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, editValueName
);
304 LoadString(hInst
, IDS_DEFAULT_VALUE_NAME
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
305 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, buffer
);
307 CheckRadioButton (hwndDlg
, IDC_FORMAT_HEX
, IDC_FORMAT_DEC
, IDC_FORMAT_HEX
);
308 _stprintf (ValueString
, _T("%lx"), dwordValueData
);
309 SetDlgItemText(hwndDlg
, IDC_VALUE_DATA
, ValueString
);
310 SetFocus(GetDlgItem(hwndDlg
, IDC_VALUE_DATA
));
314 switch (LOWORD(wParam
))
317 if (HIWORD(wParam
) == BN_CLICKED
&& dwordEditMode
== EDIT_MODE_DEC
)
319 dwordEditMode
= EDIT_MODE_HEX
;
320 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
322 if ((len
= GetWindowTextLength(hwndValue
)))
324 if (GetWindowText(hwndValue
, ValueString
, 32))
326 Value
= _tcstoul (ValueString
, &Remainder
, 10);
330 _stprintf (ValueString
, _T("%lx"), Value
);
331 SetDlgItemText(hwndDlg
, IDC_VALUE_DATA
, ValueString
);
337 if (HIWORD(wParam
) == BN_CLICKED
&& dwordEditMode
== EDIT_MODE_HEX
)
339 dwordEditMode
= EDIT_MODE_DEC
;
340 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
342 if ((len
= GetWindowTextLength(hwndValue
)))
344 if (GetWindowText(hwndValue
, ValueString
, 32))
346 Value
= _tcstoul (ValueString
, &Remainder
, 16);
350 _stprintf (ValueString
, _T("%lu"), Value
);
351 SetDlgItemText(hwndDlg
, IDC_VALUE_DATA
, ValueString
);
357 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
359 if ((len
= GetWindowTextLength(hwndValue
)))
361 if (!GetWindowText(hwndValue
, ValueString
, 32))
363 EndDialog(hwndDlg
, IDCANCEL
);
367 Base
= (dwordEditMode
== EDIT_MODE_HEX
) ? 16 : 10;
368 dwordValueData
= _tcstoul (ValueString
, &Remainder
, Base
);
372 EndDialog(hwndDlg
, IDCANCEL
);
376 EndDialog(hwndDlg
, IDOK
);
380 EndDialog(hwndDlg
, IDCANCEL
);
388 INT_PTR CALLBACK
modify_binary_dlgproc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
393 UNREFERENCED_PARAMETER(lParam
);
397 if(editValueName
&& _tcscmp(editValueName
, _T("")))
399 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, editValueName
);
404 LoadString(hInst
, IDS_DEFAULT_VALUE_NAME
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
405 SetDlgItemText(hwndDlg
, IDC_VALUE_NAME
, buffer
);
407 hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
);
408 HexEdit_LoadBuffer(hwndValue
, binValueData
, valueDataLen
);
409 /* reset the hex edit control's font */
410 SendMessage(hwndValue
, WM_SETFONT
, 0, 0);
414 switch (LOWORD(wParam
))
417 if ((hwndValue
= GetDlgItem(hwndDlg
, IDC_VALUE_DATA
)))
419 len
= (UINT
) HexEdit_GetBufferSize(hwndValue
);
420 if (len
!= valueDataLen
&& len
> 0)
422 binValueData
= HeapReAlloc(GetProcessHeap(), 0, binValueData
, len
);
426 HexEdit_CopyBuffer(hwndValue
, binValueData
, len
);
430 EndDialog(hwndDlg
, IDOK
);
433 EndDialog(hwndDlg
, IDCANCEL
);
441 BOOL
ModifyValue(HWND hwnd
, HKEY hKey
, LPCTSTR valueName
, BOOL EditBin
)
450 editValueName
= valueName
;
452 lRet
= RegQueryValueEx(hKey
, valueName
, 0, &type
, 0, &valueDataLen
);
453 if (lRet
!= ERROR_SUCCESS
&& (!_tcscmp(valueName
, _T("")) || valueName
== NULL
))
455 lRet
= ERROR_SUCCESS
; /* Allow editing of (Default) values which don't exist */
458 stringValueData
= NULL
;
462 if (lRet
!= ERROR_SUCCESS
)
464 error(hwnd
, IDS_BAD_VALUE
, valueName
);
468 if (EditBin
== FALSE
&& ((type
== REG_SZ
) || (type
== REG_EXPAND_SZ
)))
470 if (valueDataLen
> 0)
472 if (!(stringValueData
= HeapAlloc(GetProcessHeap(), 0, valueDataLen
)))
474 error(hwnd
, IDS_TOO_BIG_VALUE
, valueDataLen
);
477 lRet
= RegQueryValueEx(hKey
, valueName
, 0, 0, (LPBYTE
)stringValueData
, &valueDataLen
);
478 if (lRet
!= ERROR_SUCCESS
)
480 error(hwnd
, IDS_BAD_VALUE
, valueName
);
486 stringValueData
= NULL
;
489 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING
), hwnd
, modify_string_dlgproc
) == IDOK
)
493 lRet
= RegSetValueEx(hKey
, valueName
, 0, type
, (LPBYTE
)stringValueData
, (DWORD
) (_tcslen(stringValueData
) + 1) * sizeof(TCHAR
));
497 lRet
= RegSetValueEx(hKey
, valueName
, 0, type
, NULL
, 0);
499 if (lRet
== ERROR_SUCCESS
)
503 else if (EditBin
== FALSE
&& type
== REG_MULTI_SZ
)
505 if (valueDataLen
> 0)
507 size_t llen
, listlen
, nl_len
;
508 LPTSTR src
, lines
= NULL
;
510 if (!(stringValueData
= HeapAlloc(GetProcessHeap(), 0, valueDataLen
)))
512 error(hwnd
, IDS_TOO_BIG_VALUE
, valueDataLen
);
515 lRet
= RegQueryValueEx(hKey
, valueName
, 0, 0, (LPBYTE
)stringValueData
, &valueDataLen
);
516 if (lRet
!= ERROR_SUCCESS
)
518 error(hwnd
, IDS_BAD_VALUE
, valueName
);
522 /* convert \0 to \r\n */
523 src
= stringValueData
;
524 nl_len
= _tcslen(_T("\r\n")) * sizeof(TCHAR
);
525 listlen
= sizeof(TCHAR
);
526 lines
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, listlen
+ sizeof(TCHAR
));
527 while(*src
!= _T('\0'))
532 listlen
+= (llen
* sizeof(TCHAR
)) + nl_len
;
533 lines
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lines
, listlen
);
535 _tcscat(lines
, _T("\r\n"));
538 HeapFree(GetProcessHeap(), 0, stringValueData
);
539 stringValueData
= lines
;
543 stringValueData
= NULL
;
546 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_MULTI_STRING
), hwnd
, modify_multi_string_dlgproc
) == IDOK
)
550 /* convert \r\n to \0 */
551 BOOL EmptyLines
= FALSE
;
552 LPTSTR src
, lines
, nl
;
553 size_t linechars
, buflen
, c_nl
, dest
;
555 src
= stringValueData
;
556 buflen
= sizeof(TCHAR
);
557 lines
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buflen
+ sizeof(TCHAR
));
558 c_nl
= _tcslen(_T("\r\n"));
560 while(*src
!= _T('\0'))
562 if((nl
= _tcsstr(src
, _T("\r\n"))))
564 linechars
= nl
- src
;
574 linechars
= _tcslen(src
);
578 buflen
+= ((linechars
+ 1) * sizeof(TCHAR
));
579 lines
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lines
, buflen
);
580 memcpy((lines
+ dest
), src
, linechars
* sizeof(TCHAR
));
582 lines
[dest
++] = _T('\0');
588 src
+= linechars
+ (nl
!= NULL
? c_nl
: 0);
590 lines
[++dest
] = _T('\0');
594 warning(hwnd
, IDS_MULTI_SZ_EMPTY_STRING
);
597 lRet
= RegSetValueEx(hKey
, valueName
, 0, type
, (LPBYTE
)lines
, (DWORD
) buflen
);
598 HeapFree(GetProcessHeap(), 0, lines
);
602 lRet
= RegSetValueEx(hKey
, valueName
, 0, type
, NULL
, 0);
604 if (lRet
== ERROR_SUCCESS
)
608 else if (EditBin
== FALSE
&& type
== REG_DWORD
)
610 lRet
= RegQueryValueEx(hKey
, valueName
, 0, 0, (LPBYTE
)&dwordValueData
, &valueDataLen
);
611 if (lRet
!= ERROR_SUCCESS
)
613 error(hwnd
, IDS_BAD_VALUE
, valueName
);
617 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD
), hwnd
, modify_dword_dlgproc
) == IDOK
)
619 lRet
= RegSetValueEx(hKey
, valueName
, 0, type
, (LPBYTE
)&dwordValueData
, sizeof(DWORD
));
620 if (lRet
== ERROR_SUCCESS
)
624 else if (EditBin
== TRUE
|| type
== REG_NONE
|| type
== REG_BINARY
)
628 int len_vname
= lstrlen(valueName
);
632 if(!(u_valuename
= HeapAlloc(GetProcessHeap(), 0, (len_vname
+ 1) * sizeof(WCHAR
))))
634 error(hwnd
, IDS_TOO_BIG_VALUE
, len_vname
);
637 /* convert the ansi value name to an unicode string */
638 MultiByteToWideChar(CP_ACP
, 0, valueName
, -1, u_valuename
, len_vname
+ 1);
639 valueDataLen
*= sizeof(WCHAR
);
646 if(!(binValueData
= HeapAlloc(GetProcessHeap(), 0, valueDataLen
)))
648 error(hwnd
, IDS_TOO_BIG_VALUE
, valueDataLen
);
652 /* force to use the unicode version, so editing strings in binary mode is correct */
653 lRet
= RegQueryValueExW(hKey
,
659 0, 0, (LPBYTE
)binValueData
, &valueDataLen
);
660 if (lRet
!= ERROR_SUCCESS
)
662 HeapFree(GetProcessHeap(), 0, binValueData
);
665 HeapFree(GetProcessHeap(), 0, u_valuename
);
667 error(hwnd
, IDS_BAD_VALUE
, valueName
);
676 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_BIN_DATA
), hwnd
, modify_binary_dlgproc
) == IDOK
)
678 /* force to use the unicode version, so editing strings in binary mode is correct */
679 lRet
= RegSetValueExW(hKey
,
685 0, type
, (LPBYTE
)binValueData
, valueDataLen
);
686 if (lRet
== ERROR_SUCCESS
)
689 if(binValueData
!= NULL
)
690 HeapFree(GetProcessHeap(), 0, binValueData
);
693 HeapFree(GetProcessHeap(), 0, u_valuename
);
698 error(hwnd
, IDS_UNSUPPORTED_TYPE
, type
);
703 HeapFree(GetProcessHeap(), 0, stringValueData
);
704 stringValueData
= NULL
;
709 BOOL
DeleteKey(HWND hwnd
, HKEY hKeyRoot
, LPCTSTR keyPath
)
711 TCHAR msg
[128], caption
[128];
716 lRet
= RegOpenKeyEx(hKeyRoot
, keyPath
, 0, KEY_READ
|KEY_SET_VALUE
, &hKey
);
717 if (lRet
!= ERROR_SUCCESS
) {
718 error_code_messagebox(hwnd
, lRet
);
722 LoadString(hInst
, IDS_QUERY_DELETE_KEY_CONFIRM
, caption
, sizeof(caption
)/sizeof(TCHAR
));
723 LoadString(hInst
, IDS_QUERY_DELETE_KEY_ONE
, msg
, sizeof(msg
)/sizeof(TCHAR
));
725 if (MessageBox(g_pChildWnd
->hWnd
, msg
, caption
, MB_ICONQUESTION
| MB_YESNO
) != IDYES
)
728 lRet
= SHDeleteKey(hKeyRoot
, keyPath
);
729 if (lRet
!= ERROR_SUCCESS
) {
730 error(hwnd
, IDS_BAD_KEY
, keyPath
);