d2d1: Remove unused D3D10 interfaces.
[wine.git] / programs / regedit / framewnd.c
blobbb843a89af45ff2a4bcafc4d80f6c0c1cf5c6699
1 /*
2 * Regedit frame window
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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 St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
23 #include <windows.h>
24 #include <commctrl.h>
25 #include <commdlg.h>
26 #include <cderr.h>
27 #include <stdlib.h>
28 #include <shellapi.h>
30 #include "main.h"
31 #include "wine/debug.h"
32 #include "wine/heap.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
36 /********************************************************************************
37 * Global and Local Variables:
40 static const WCHAR favoritesKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p','l','e','t','s','\\','R','e','g','E','d','i','t','\\','F','a','v','o','r','i','t','e','s',0};
41 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
42 static WCHAR favoriteName[128];
43 static WCHAR searchString[128];
44 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
46 static WCHAR FileNameBuffer[_MAX_PATH];
47 static WCHAR FileTitleBuffer[_MAX_PATH];
48 static WCHAR FilterBuffer[_MAX_PATH];
49 static WCHAR expandW[32], collapseW[32];
50 static WCHAR modifyW[32], modify_binaryW[64];
52 /*******************************************************************************
53 * Local module support methods
56 static void resize_frame_rect(HWND hWnd, PRECT prect)
58 if (IsWindowVisible(hStatusBar)) {
59 RECT rt;
61 SetupStatusBar(hWnd, TRUE);
62 GetClientRect(hStatusBar, &rt);
63 prect->bottom -= rt.bottom;
65 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
68 static void resize_frame_client(HWND hWnd)
70 RECT rect;
72 GetClientRect(hWnd, &rect);
73 resize_frame_rect(hWnd, &rect);
76 /********************************************************************************/
78 static void OnEnterMenuLoop(HWND hWnd)
80 int nParts;
81 WCHAR empty = 0;
83 /* Update the status bar pane sizes */
84 nParts = -1;
85 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
86 bInMenuLoop = TRUE;
87 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
90 static void OnExitMenuLoop(HWND hWnd)
92 bInMenuLoop = FALSE;
93 /* Update the status bar pane sizes*/
94 SetupStatusBar(hWnd, TRUE);
95 UpdateStatusBar();
98 static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
100 TVITEMW item;
101 MENUITEMINFOW info;
103 item.hItem = selection;
104 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
105 item.stateMask = TVIS_EXPANDED;
106 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);
108 info.cbSize = sizeof(MENUITEMINFOW);
109 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
110 info.fType = MFT_STRING;
111 info.fState = MFS_ENABLED;
112 info.dwTypeData = expandW;
114 if (!item.cChildren)
116 info.fState = MFS_GRAYED;
117 goto update;
120 if (item.state & TVIS_EXPANDED)
121 info.dwTypeData = collapseW;
123 update:
124 SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
127 static void update_modify_items(HMENU hMenu, int index)
129 unsigned int state = MF_ENABLED;
131 if (index == -1)
132 state = MF_GRAYED;
134 EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
135 EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
138 static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
140 unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
142 if (!g_pChildWnd->nFocusPanel)
144 if (!keyName || !*keyName)
145 state_d = state_r = MF_GRAYED;
147 else if (index < 1)
149 state_r = MF_GRAYED;
150 if (index == -1) state_d = MF_GRAYED;
153 EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
154 EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
157 static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
159 unsigned int state = MF_ENABLED, i;
160 unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
161 ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
162 ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
164 if (!keyName)
165 state = MF_GRAYED;
167 for (i = 0; i < ARRAY_SIZE(items); i++)
168 EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
171 static void UpdateMenuItems(HMENU hMenu) {
172 HWND hwndTV = g_pChildWnd->hTreeWnd;
173 HKEY hRootKey = NULL;
174 LPWSTR keyName;
175 HTREEITEM selection;
176 int index;
178 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
179 keyName = GetItemPath(hwndTV, selection, &hRootKey);
180 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
181 MAKELPARAM(LVNI_SELECTED, 0));
183 update_expand_or_collapse_item(hwndTV, selection, hMenu);
184 update_modify_items(hMenu, index);
185 update_delete_and_rename_items(hMenu, keyName, index);
186 update_new_items_and_copy_keyname(hMenu, keyName);
187 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
188 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
189 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
191 heap_free(keyName);
194 static void add_remove_modify_menu_items(HMENU hMenu)
196 if (!g_pChildWnd->nFocusPanel)
198 while (GetMenuItemCount(hMenu) > 9)
199 DeleteMenu(hMenu, 0, MF_BYPOSITION);
201 else if (GetMenuItemCount(hMenu) < 10)
203 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
204 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
205 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
209 static int add_favourite_key_items(HMENU hMenu, HWND hList)
211 HKEY hkey;
212 LONG rc;
213 DWORD num_values, max_value_len, value_len, type, i = 0;
214 WCHAR *value_name;
216 rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
217 if (rc != ERROR_SUCCESS) return 0;
219 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
220 &max_value_len, NULL, NULL, NULL);
221 if (rc != ERROR_SUCCESS)
223 ERR("RegQueryInfoKey failed: %d\n", rc);
224 goto exit;
227 if (!num_values) goto exit;
229 max_value_len++;
230 value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
232 if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
234 for (i = 0; i < num_values; i++)
236 value_len = max_value_len;
237 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
238 if (rc == ERROR_SUCCESS && type == REG_SZ)
240 if (hMenu)
241 AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
242 else if (hList)
243 SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
247 heap_free(value_name);
248 exit:
249 RegCloseKey(hkey);
250 return i;
253 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
255 if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
256 add_remove_modify_menu_items(hMenu);
257 else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
259 while (GetMenuItemCount(hMenu) > 2)
260 DeleteMenu(hMenu, 2, MF_BYPOSITION);
262 add_favourite_key_items(hMenu, NULL);
265 UpdateMenuItems(hMenu);
268 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
270 WCHAR str[100];
272 str[0] = 0;
273 if (nFlags & MF_POPUP) {
274 if (hSysMenu != GetMenu(hWnd)) {
275 if (nItemID == 2) nItemID = 5;
278 if (LoadStringW(hInst, nItemID, str, 100)) {
279 /* load appropriate string*/
280 LPWSTR lpsz = str;
281 /* first newline terminates actual string*/
282 lpsz = wcschr(lpsz, '\n');
283 if (lpsz != NULL)
284 *lpsz = '\0';
286 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
289 void SetupStatusBar(HWND hWnd, BOOL bResize)
291 RECT rc;
292 int nParts;
293 GetClientRect(hWnd, &rc);
294 nParts = rc.right;
295 /* nParts = -1;*/
296 if (bResize)
297 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
298 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
299 UpdateStatusBar();
302 void UpdateStatusBar(void)
304 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
305 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
306 heap_free(fullPath);
309 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
311 BOOL vis = IsWindowVisible(hchild);
312 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
314 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
315 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
316 resize_frame_client(hWnd);
319 static BOOL CheckCommDlgError(HWND hWnd)
321 DWORD dwErrorCode = CommDlgExtendedError();
322 switch (dwErrorCode) {
323 case CDERR_DIALOGFAILURE:
324 break;
325 case CDERR_FINDRESFAILURE:
326 break;
327 case CDERR_NOHINSTANCE:
328 break;
329 case CDERR_INITIALIZATION:
330 break;
331 case CDERR_NOHOOK:
332 break;
333 case CDERR_LOCKRESFAILURE:
334 break;
335 case CDERR_NOTEMPLATE:
336 break;
337 case CDERR_LOADRESFAILURE:
338 break;
339 case CDERR_STRUCTSIZE:
340 break;
341 case CDERR_LOADSTRFAILURE:
342 break;
343 case FNERR_BUFFERTOOSMALL:
344 break;
345 case CDERR_MEMALLOCFAILURE:
346 break;
347 case FNERR_INVALIDFILENAME:
348 break;
349 case CDERR_MEMLOCKFAILURE:
350 break;
351 case FNERR_SUBCLASSFAILURE:
352 break;
353 default:
354 break;
356 return TRUE;
359 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
361 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
363 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
364 pOpenFileName->lCustData = (LPARAM)heap_xalloc((len + 1) * sizeof(WCHAR));
365 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
367 else
369 pOpenFileName->lCustData = (LPARAM)heap_xalloc(sizeof(WCHAR));
370 *(WCHAR *)pOpenFileName->lCustData = 0;
374 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
376 static OPENFILENAMEW* pOpenFileName;
377 OFNOTIFYW *pOfNotify;
379 switch (uiMsg) {
380 case WM_INITDIALOG:
381 pOpenFileName = (OPENFILENAMEW*)lParam;
382 break;
383 case WM_COMMAND:
384 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
385 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
386 break;
387 case WM_NOTIFY:
388 pOfNotify = (OFNOTIFYW*)lParam;
389 switch (pOfNotify->hdr.code)
391 case CDN_INITDONE:
393 BOOL export_branch = FALSE;
394 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
395 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
396 if (path && path[0])
397 export_branch = TRUE;
398 heap_free(path);
399 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
400 break;
402 case CDN_FILEOK:
403 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
404 break;
406 break;
407 default:
408 break;
410 return 0L;
414 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
416 memset(pofn, 0, sizeof(OPENFILENAMEW));
417 pofn->lStructSize = sizeof(OPENFILENAMEW);
418 pofn->hwndOwner = hWnd;
419 pofn->hInstance = hInst;
421 if (FilterBuffer[0] == 0)
423 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
424 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
426 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
427 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
428 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
429 swprintf( FilterBuffer, ARRAY_SIZE(FilterBuffer), filterW,
430 filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
432 pofn->lpstrFilter = FilterBuffer;
433 pofn->nFilterIndex = 1;
434 pofn->lpstrFile = FileNameBuffer;
435 pofn->nMaxFile = _MAX_PATH;
436 pofn->lpstrFileTitle = FileTitleBuffer;
437 pofn->nMaxFileTitle = _MAX_PATH;
438 pofn->Flags = OFN_HIDEREADONLY;
439 /* some other fields may be set by the caller */
440 return TRUE;
443 static BOOL import_registry_filename(LPWSTR filename)
445 static const WCHAR rb_mode[] = {'r','b',0};
447 BOOL Success;
448 FILE* reg_file = _wfopen(filename, rb_mode);
450 if(!reg_file)
451 return FALSE;
453 Success = import_registry_file(reg_file);
455 if(fclose(reg_file) != 0)
456 Success = FALSE;
458 return Success;
461 static BOOL ImportRegistryFile(HWND hWnd)
463 OPENFILENAMEW ofn;
464 WCHAR title[128];
465 HKEY root_key = NULL;
466 WCHAR *key_path;
468 InitOpenFileName(hWnd, &ofn);
469 ofn.Flags |= OFN_ENABLESIZING;
470 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, ARRAY_SIZE(title));
471 ofn.lpstrTitle = title;
472 if (GetOpenFileNameW(&ofn)) {
473 if (!import_registry_filename(ofn.lpstrFile)) {
474 messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
475 return FALSE;
476 } else {
477 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
478 IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
480 } else {
481 CheckCommDlgError(hWnd);
483 RefreshTreeView(g_pChildWnd->hTreeWnd);
485 key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
486 RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
487 heap_free(key_path);
489 return TRUE;
493 static BOOL ExportRegistryFile(HWND hWnd)
495 OPENFILENAMEW ofn;
496 WCHAR title[128];
498 InitOpenFileName(hWnd, &ofn);
499 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, ARRAY_SIZE(title));
500 ofn.lpstrTitle = title;
501 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
502 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
503 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
504 if (GetSaveFileNameW(&ofn)) {
505 BOOL result;
506 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
507 if (!result) {
508 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
509 return FALSE;
511 } else {
512 CheckCommDlgError(hWnd);
514 return TRUE;
517 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
519 #if 1
520 PRINTDLGW pd;
522 ZeroMemory(&pd, sizeof(PRINTDLGW));
523 pd.lStructSize = sizeof(PRINTDLGW);
524 pd.hwndOwner = hWnd;
525 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
526 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
527 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
528 pd.nCopies = 1;
529 pd.nFromPage = 0xFFFF;
530 pd.nToPage = 0xFFFF;
531 pd.nMinPage = 1;
532 pd.nMaxPage = 0xFFFF;
533 if (PrintDlgW(&pd)) {
534 FIXME("printing is not yet implemented.\n");
535 /* GDI calls to render output. */
536 DeleteDC(pd.hDC); /* Delete DC when done.*/
538 #else
539 HRESULT hResult;
540 PRINTDLGEXW pd;
542 hResult = PrintDlgExW(&pd);
543 if (hResult == S_OK) {
544 switch (pd.dwResultAction) {
545 case PD_RESULT_APPLY:
546 /*The user clicked the Apply button and later clicked the Cancel button. This indicates that the user wants to apply the changes made in the property sheet, but does not yet want to print. The PRINTDLGEX structure contains the information specified by the user at the time the Apply button was clicked. */
547 FIXME("printing is not yet implemented.\n");
548 break;
549 case PD_RESULT_CANCEL:
550 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
551 break;
552 case PD_RESULT_PRINT:
553 FIXME("printing is not yet implemented.\n");
554 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
555 break;
556 default:
557 break;
559 } else {
560 switch (hResult) {
561 case E_OUTOFMEMORY:
562 /*Insufficient memory. */
563 break;
564 case E_INVALIDARG:
565 /* One or more arguments are invalid. */
566 break;
567 case E_POINTER:
568 /*Invalid pointer. */
569 break;
570 case E_HANDLE:
571 /*Invalid handle. */
572 break;
573 case E_FAIL:
574 /*Unspecified error. */
575 break;
576 default:
577 break;
579 return FALSE;
581 #endif
582 return TRUE;
585 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
587 BOOL result;
589 result = OpenClipboard(hWnd);
590 if (result) {
591 result = EmptyClipboard();
592 if (result) {
593 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
594 HANDLE hClipData = GlobalAlloc(GHND, len);
595 LPVOID pLoc = GlobalLock(hClipData);
596 lstrcpyW(pLoc, keyName);
597 GlobalUnlock(hClipData);
598 SetClipboardData(CF_UNICODETEXT, hClipData);
600 } else {
601 /* error emptying clipboard*/
602 /* DWORD dwError = GetLastError(); */
605 if (!CloseClipboard()) {
606 /* error closing clipboard*/
607 /* DWORD dwError = GetLastError(); */
610 } else {
611 /* error opening clipboard*/
612 /* DWORD dwError = GetLastError(); */
615 return result;
618 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
620 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
622 switch(uMsg) {
623 case WM_INITDIALOG:
624 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
625 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
626 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
627 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
628 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
629 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
630 SetWindowTextW(hwndValue, searchString);
631 return TRUE;
632 case WM_COMMAND:
633 switch(LOWORD(wParam)) {
634 case IDC_VALUE_NAME:
635 if (HIWORD(wParam) == EN_UPDATE) {
636 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
637 return TRUE;
639 break;
640 case IDOK:
641 if (GetWindowTextLengthW(hwndValue)>0) {
642 int mask = 0;
643 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
644 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
645 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
646 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
647 searchMask = mask;
648 GetWindowTextW(hwndValue, searchString, 128);
649 EndDialog(hwndDlg, IDOK);
651 return TRUE;
652 case IDCANCEL:
653 EndDialog(hwndDlg, IDCANCEL);
654 return TRUE;
656 break;
658 return FALSE;
661 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
663 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
665 switch(uMsg) {
666 case WM_INITDIALOG:
668 HTREEITEM selected;
669 TVITEMW item;
670 WCHAR buf[128];
672 selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
674 item.mask = TVIF_HANDLE | TVIF_TEXT;
675 item.hItem = selected;
676 item.pszText = buf;
677 item.cchTextMax = ARRAY_SIZE(buf);
678 SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETITEMW, 0, (LPARAM)&item);
680 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
681 SetWindowTextW(hwndValue, buf);
682 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
683 return TRUE;
685 case WM_COMMAND:
686 switch(LOWORD(wParam)) {
687 case IDC_VALUE_NAME:
688 if (HIWORD(wParam) == EN_UPDATE) {
689 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
690 return TRUE;
692 break;
693 case IDOK:
694 if (GetWindowTextLengthW(hwndValue)>0) {
695 GetWindowTextW(hwndValue, favoriteName, 128);
696 EndDialog(hwndDlg, IDOK);
698 return TRUE;
699 case IDCANCEL:
700 EndDialog(hwndDlg, IDCANCEL);
701 return TRUE;
703 break;
705 return FALSE;
708 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
710 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
712 switch(uMsg) {
713 case WM_INITDIALOG:
714 if (!add_favourite_key_items(NULL, hwndList))
715 return FALSE;
716 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
717 return TRUE;
718 case WM_COMMAND:
719 switch(LOWORD(wParam)) {
720 case IDC_NAME_LIST:
721 if (HIWORD(wParam) == LBN_SELCHANGE) {
722 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
723 return TRUE;
725 break;
726 case IDOK: {
727 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
728 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
729 if (len>0) {
730 WCHAR *lpName = heap_xalloc((len + 1) * sizeof(WCHAR));
731 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
732 if (len>127)
733 lpName[127] = '\0';
734 lstrcpyW(favoriteName, lpName);
735 EndDialog(hwndDlg, IDOK);
736 heap_free(lpName);
738 return TRUE;
740 case IDCANCEL:
741 EndDialog(hwndDlg, IDCANCEL);
742 return TRUE;
744 break;
746 return FALSE;
749 /*******************************************************************************
751 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
753 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
756 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
758 HKEY hKeyRoot = 0;
759 DWORD valueType;
761 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
762 HKEY hKey;
763 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
764 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
765 WCHAR namebuf[KEY_MAX_LEN];
766 BYTE valuebuf[4096];
767 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
768 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
769 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
770 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
771 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
773 RegCloseKey(hKey);
775 return TRUE;
777 switch (LOWORD(wParam)) {
778 case ID_REGISTRY_IMPORTREGISTRYFILE:
779 ImportRegistryFile(hWnd);
780 break;
781 case ID_EDIT_EXPORT:
782 case ID_REGISTRY_EXPORTREGISTRYFILE:
783 ExportRegistryFile(hWnd);
784 break;
785 case ID_REGISTRY_PRINT:
787 const WCHAR empty = 0;
788 PrintRegistryHive(hWnd, &empty);
789 break;
791 case ID_EDIT_DELETE:
793 HWND hWndDelete = GetFocus();
794 if (hWndDelete == g_pChildWnd->hTreeWnd) {
795 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
796 if (keyPath == 0 || *keyPath == 0) {
797 MessageBeep(MB_ICONHAND);
798 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
799 DeleteNode(g_pChildWnd->hTreeWnd, 0);
801 heap_free(keyPath);
802 } else if (hWndDelete == g_pChildWnd->hListWnd) {
803 unsigned int num_selected, index, focus_idx;
804 WCHAR *keyPath;
806 num_selected = SendMessageW(g_pChildWnd->hListWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
808 if (!num_selected)
809 break;
810 else if (num_selected == 1)
811 index = IDS_DELETE_VALUE_TEXT;
812 else
813 index = IDS_DELETE_VALUE_TEXT_MULTIPLE;
815 if (messagebox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_VALUE_TITLE, index) != IDYES)
816 break;
818 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
820 focus_idx = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
821 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
823 while (index != -1)
825 WCHAR *valueName = GetItemText(g_pChildWnd->hListWnd, index);
826 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
828 heap_free(valueName);
829 break;
831 heap_free(valueName);
832 SendMessageW(g_pChildWnd->hListWnd, LVM_DELETEITEM, index, 0L);
833 /* the default value item is always visible, so add it back in */
834 if (!index)
836 AddEntryToList(g_pChildWnd->hListWnd, NULL, REG_SZ, NULL, 0, 0);
837 if (!focus_idx)
839 LVITEMW item;
840 item.state = item.stateMask = LVIS_FOCUSED;
841 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
844 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
846 heap_free(keyPath);
847 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
848 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
849 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
851 break;
853 case ID_EDIT_MODIFY:
854 case ID_EDIT_MODIFY_BIN:
856 WCHAR *valueName = GetValueName(g_pChildWnd->hListWnd);
857 WCHAR *keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
858 ModifyValue(hWnd, hKeyRoot, keyPath, valueName);
859 heap_free(keyPath);
860 heap_free(valueName);
861 break;
863 case ID_EDIT_FIND:
864 case ID_EDIT_FINDNEXT:
866 HTREEITEM hItem;
867 if (LOWORD(wParam) == ID_EDIT_FIND &&
868 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
869 break;
870 if (!*searchString)
871 break;
872 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
873 if (hItem) {
874 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
875 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
876 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
877 SetCursor(hcursorOld);
878 if (hItem) {
879 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
880 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
881 UpdateWindow(g_pChildWnd->hTreeWnd);
882 if (row != -1) {
883 LVITEMW item;
885 item.state = 0;
886 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
887 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
889 item.state = LVIS_FOCUSED | LVIS_SELECTED;
890 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
891 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
892 SetFocus(g_pChildWnd->hListWnd);
893 } else {
894 SetFocus(g_pChildWnd->hTreeWnd);
896 } else {
897 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
900 break;
902 case ID_EDIT_COPYKEYNAME:
904 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
905 if (fullPath) {
906 CopyKeyName(hWnd, fullPath);
907 heap_free(fullPath);
909 break;
911 case ID_EDIT_NEW_KEY:
913 WCHAR newKeyW[MAX_NEW_KEY_LEN];
914 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
915 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
916 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
917 StartKeyRename(g_pChildWnd->hTreeWnd);
919 heap_free(keyPath);
921 break;
922 case ID_EDIT_NEW_STRINGVALUE:
923 valueType = REG_SZ;
924 goto create_value;
925 case ID_EDIT_NEW_EXPANDVALUE:
926 valueType = REG_EXPAND_SZ;
927 goto create_value;
928 case ID_EDIT_NEW_MULTI_STRINGVALUE:
929 valueType = REG_MULTI_SZ;
930 goto create_value;
931 case ID_EDIT_NEW_BINARYVALUE:
932 valueType = REG_BINARY;
933 goto create_value;
934 case ID_EDIT_NEW_DWORDVALUE:
935 valueType = REG_DWORD;
936 /* fall through */
937 create_value:
939 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
940 WCHAR newKey[MAX_NEW_KEY_LEN];
941 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey))
942 StartValueRename(g_pChildWnd->hListWnd);
943 heap_free(keyPath);
945 break;
946 case ID_EDIT_RENAME:
948 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
949 if (keyPath == 0 || *keyPath == 0) {
950 MessageBeep(MB_ICONHAND);
951 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
952 StartKeyRename(g_pChildWnd->hTreeWnd);
953 } else if (GetFocus() == g_pChildWnd->hListWnd) {
954 StartValueRename(g_pChildWnd->hListWnd);
956 heap_free(keyPath);
957 break;
959 case ID_TREE_EXPAND_COLLAPSE:
961 HTREEITEM selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
962 SendMessageW(g_pChildWnd->hTreeWnd, TVM_EXPAND, TVE_TOGGLE, (LPARAM)selected);
963 break;
965 case ID_REGISTRY_PRINTERSETUP:
966 /*PRINTDLG pd;*/
967 /*PrintDlg(&pd);*/
968 /*PAGESETUPDLG psd;*/
969 /*PageSetupDlg(&psd);*/
970 break;
971 case ID_REGISTRY_OPENLOCAL:
972 break;
973 case ID_REGISTRY_EXIT:
974 DestroyWindow(hWnd);
975 break;
976 case ID_FAVORITES_ADDTOFAVORITES:
978 HKEY hKey;
979 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
980 if (lpKeyPath) {
981 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
982 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
983 0, NULL, 0,
984 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
985 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
986 RegCloseKey(hKey);
989 heap_free(lpKeyPath);
991 break;
993 case ID_FAVORITES_REMOVEFAVORITE:
995 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
996 HKEY hKey;
997 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
998 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
999 RegDeleteValueW(hKey, favoriteName);
1000 RegCloseKey(hKey);
1003 break;
1005 case ID_VIEW_REFRESH:
1007 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1008 RefreshTreeView(g_pChildWnd->hTreeWnd);
1009 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
1010 heap_free(keyPath);
1012 break;
1013 /*case ID_OPTIONS_TOOLBAR:*/
1014 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1015 /* break;*/
1016 case ID_VIEW_STATUSBAR:
1017 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1018 break;
1019 case ID_HELP_HELPTOPICS:
1021 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1022 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
1023 break;
1025 case ID_HELP_ABOUT:
1026 ShowAboutBox(hWnd);
1027 break;
1028 case ID_VIEW_SPLIT: {
1029 RECT rt;
1030 POINT pt, pts;
1031 GetClientRect(g_pChildWnd->hWnd, &rt);
1032 pt.x = rt.left + g_pChildWnd->nSplitPos;
1033 pt.y = (rt.bottom / 2);
1034 pts = pt;
1035 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
1036 SetCursorPos(pts.x, pts.y);
1037 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
1038 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1040 return TRUE;
1042 default:
1043 return FALSE;
1046 return TRUE;
1049 /********************************************************************************
1051 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1053 * PURPOSE: Processes messages for the main frame window.
1055 * WM_COMMAND - process the application menu
1056 * WM_DESTROY - post a quit message and return
1060 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1062 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
1064 switch (message) {
1065 case WM_CREATE:
1066 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
1067 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1068 hWnd, NULL, hInst, 0);
1069 LoadStringW(hInst, IDS_EXPAND, expandW, ARRAY_SIZE(expandW));
1070 LoadStringW(hInst, IDS_COLLAPSE, collapseW, ARRAY_SIZE(collapseW));
1071 LoadStringW(hInst, IDS_EDIT_MODIFY, modifyW, ARRAY_SIZE(modifyW));
1072 LoadStringW(hInst, IDS_EDIT_MODIFY_BIN, modify_binaryW, ARRAY_SIZE(modify_binaryW));
1073 break;
1074 case WM_COMMAND:
1075 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1076 return DefWindowProcW(hWnd, message, wParam, lParam);
1077 break;
1078 case WM_ACTIVATE:
1079 if (LOWORD(hWnd))
1080 SetFocus(g_pChildWnd->hWnd);
1081 break;
1082 case WM_SIZE:
1083 resize_frame_client(hWnd);
1084 break;
1085 case WM_TIMER:
1086 break;
1087 case WM_ENTERMENULOOP:
1088 OnEnterMenuLoop(hWnd);
1089 break;
1090 case WM_EXITMENULOOP:
1091 OnExitMenuLoop(hWnd);
1092 break;
1093 case WM_INITMENUPOPUP:
1094 if (!HIWORD(lParam))
1095 OnInitMenuPopup(hWnd, (HMENU)wParam);
1096 break;
1097 case WM_MENUSELECT:
1098 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1099 break;
1100 case WM_DESTROY:
1102 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1103 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
1104 PostQuitMessage(0);
1106 default:
1107 return DefWindowProcW(hWnd, message, wParam, lParam);
1109 return 0;