regedit: Use the heap_*() functions in framewnd.c where possible.
[wine.git] / programs / regedit / framewnd.c
blobc3cc996e7414ed022d1f8bce5cdef263494c7481
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 <stdio.h>
29 #include <shellapi.h>
31 #include "main.h"
32 #include "regproc.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
38 /********************************************************************************
39 * Global and Local Variables:
42 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};
43 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
44 static WCHAR favoriteName[128];
45 static WCHAR searchString[128];
46 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
48 static WCHAR FileNameBuffer[_MAX_PATH];
49 static WCHAR FileTitleBuffer[_MAX_PATH];
50 static WCHAR FilterBuffer[_MAX_PATH];
51 static WCHAR expandW[32], collapseW[32];
52 static WCHAR modifyW[32], modify_binaryW[64];
54 /*******************************************************************************
55 * Local module support methods
58 static void resize_frame_rect(HWND hWnd, PRECT prect)
60 RECT rt;
62 if (IsWindowVisible(hToolBar)) {
63 SendMessageW(hToolBar, WM_SIZE, 0, 0);
64 GetClientRect(hToolBar, &rt);
65 prect->top = rt.bottom+3;
66 prect->bottom -= rt.bottom+3;
69 if (IsWindowVisible(hStatusBar)) {
70 SetupStatusBar(hWnd, TRUE);
71 GetClientRect(hStatusBar, &rt);
72 prect->bottom -= rt.bottom;
74 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
77 static void resize_frame_client(HWND hWnd)
79 RECT rect;
81 GetClientRect(hWnd, &rect);
82 resize_frame_rect(hWnd, &rect);
85 /********************************************************************************/
87 static void OnEnterMenuLoop(HWND hWnd)
89 int nParts;
90 WCHAR empty = 0;
92 /* Update the status bar pane sizes */
93 nParts = -1;
94 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
95 bInMenuLoop = TRUE;
96 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
99 static void OnExitMenuLoop(HWND hWnd)
101 bInMenuLoop = FALSE;
102 /* Update the status bar pane sizes*/
103 SetupStatusBar(hWnd, TRUE);
104 UpdateStatusBar();
107 static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
109 TVITEMW item;
110 MENUITEMINFOW info;
112 item.hItem = selection;
113 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
114 item.stateMask = TVIS_EXPANDED;
115 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);
117 info.cbSize = sizeof(MENUITEMINFOW);
118 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
119 info.fType = MFT_STRING;
120 info.fState = MFS_ENABLED;
121 info.dwTypeData = expandW;
123 if (!item.cChildren)
125 info.fState = MFS_GRAYED;
126 goto update;
129 if (item.state & TVIS_EXPANDED)
130 info.dwTypeData = collapseW;
132 update:
133 SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
136 static void update_modify_items(HMENU hMenu, int index)
138 unsigned int state = MF_ENABLED;
140 if (index == -1)
141 state = MF_GRAYED;
143 EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
144 EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
147 static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
149 unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
151 if (!g_pChildWnd->nFocusPanel)
153 if (!keyName || !*keyName)
154 state_d = state_r = MF_GRAYED;
156 else if (index < 1)
158 state_r = MF_GRAYED;
159 if (index == -1) state_d = MF_GRAYED;
162 EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
163 EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
166 static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
168 unsigned int state = MF_ENABLED, i;
169 unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
170 ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
171 ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
173 if (!keyName)
174 state = MF_GRAYED;
176 for (i = 0; i < COUNT_OF(items); i++)
177 EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
180 static void UpdateMenuItems(HMENU hMenu) {
181 HWND hwndTV = g_pChildWnd->hTreeWnd;
182 HKEY hRootKey = NULL;
183 LPWSTR keyName;
184 HTREEITEM selection;
185 int index;
187 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
188 keyName = GetItemPath(hwndTV, selection, &hRootKey);
189 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
190 MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
192 update_expand_or_collapse_item(hwndTV, selection, hMenu);
193 update_modify_items(hMenu, index);
194 update_delete_and_rename_items(hMenu, keyName, index);
195 update_new_items_and_copy_keyname(hMenu, keyName);
196 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
197 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
198 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
200 heap_free(keyName);
203 static void add_remove_modify_menu_items(HMENU hMenu)
205 if (!g_pChildWnd->nFocusPanel)
207 while (GetMenuItemCount(hMenu) > 9)
208 DeleteMenu(hMenu, 0, MF_BYPOSITION);
210 else if (GetMenuItemCount(hMenu) < 10)
212 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
213 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
214 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
218 static int add_favourite_key_items(HMENU hMenu, HWND hList)
220 HKEY hkey;
221 LONG rc;
222 DWORD num_values, max_value_len, value_len, type, i = 0;
223 WCHAR *value_name;
225 rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
226 if (rc != ERROR_SUCCESS) return 0;
228 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
229 &max_value_len, NULL, NULL, NULL);
230 if (rc != ERROR_SUCCESS)
232 ERR("RegQueryInfoKey failed: %d\n", rc);
233 goto exit;
236 if (!num_values) goto exit;
238 max_value_len++;
239 value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
241 if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
243 for (i = 0; i < num_values; i++)
245 value_len = max_value_len;
246 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
247 if (rc == ERROR_SUCCESS && type == REG_SZ)
249 if (hMenu)
250 AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
251 else if (hList)
252 SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
256 heap_free(value_name);
257 exit:
258 RegCloseKey(hkey);
259 return i;
262 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
264 if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
265 add_remove_modify_menu_items(hMenu);
266 else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
268 while (GetMenuItemCount(hMenu) > 2)
269 DeleteMenu(hMenu, 2, MF_BYPOSITION);
271 add_favourite_key_items(hMenu, NULL);
274 UpdateMenuItems(hMenu);
277 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
279 WCHAR str[100];
281 str[0] = 0;
282 if (nFlags & MF_POPUP) {
283 if (hSysMenu != GetMenu(hWnd)) {
284 if (nItemID == 2) nItemID = 5;
287 if (LoadStringW(hInst, nItemID, str, 100)) {
288 /* load appropriate string*/
289 LPWSTR lpsz = str;
290 /* first newline terminates actual string*/
291 lpsz = strchrW(lpsz, '\n');
292 if (lpsz != NULL)
293 *lpsz = '\0';
295 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
298 void SetupStatusBar(HWND hWnd, BOOL bResize)
300 RECT rc;
301 int nParts;
302 GetClientRect(hWnd, &rc);
303 nParts = rc.right;
304 /* nParts = -1;*/
305 if (bResize)
306 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
307 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
308 UpdateStatusBar();
311 void UpdateStatusBar(void)
313 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
314 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
315 heap_free(fullPath);
318 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
320 BOOL vis = IsWindowVisible(hchild);
321 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
323 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
324 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
325 resize_frame_client(hWnd);
328 static BOOL CheckCommDlgError(HWND hWnd)
330 DWORD dwErrorCode = CommDlgExtendedError();
331 switch (dwErrorCode) {
332 case CDERR_DIALOGFAILURE:
333 break;
334 case CDERR_FINDRESFAILURE:
335 break;
336 case CDERR_NOHINSTANCE:
337 break;
338 case CDERR_INITIALIZATION:
339 break;
340 case CDERR_NOHOOK:
341 break;
342 case CDERR_LOCKRESFAILURE:
343 break;
344 case CDERR_NOTEMPLATE:
345 break;
346 case CDERR_LOADRESFAILURE:
347 break;
348 case CDERR_STRUCTSIZE:
349 break;
350 case CDERR_LOADSTRFAILURE:
351 break;
352 case FNERR_BUFFERTOOSMALL:
353 break;
354 case CDERR_MEMALLOCFAILURE:
355 break;
356 case FNERR_INVALIDFILENAME:
357 break;
358 case CDERR_MEMLOCKFAILURE:
359 break;
360 case FNERR_SUBCLASSFAILURE:
361 break;
362 default:
363 break;
365 return TRUE;
368 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
370 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
372 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
373 pOpenFileName->lCustData = (LPARAM)heap_xalloc((len + 1) * sizeof(WCHAR));
374 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
376 else
377 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
380 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
382 static OPENFILENAMEW* pOpenFileName;
383 OFNOTIFYW *pOfNotify;
385 switch (uiMsg) {
386 case WM_INITDIALOG:
387 pOpenFileName = (OPENFILENAMEW*)lParam;
388 break;
389 case WM_COMMAND:
390 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
391 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
392 break;
393 case WM_NOTIFY:
394 pOfNotify = (OFNOTIFYW*)lParam;
395 switch (pOfNotify->hdr.code)
397 case CDN_INITDONE:
399 BOOL export_branch = FALSE;
400 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
401 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
402 if (path && path[0])
403 export_branch = TRUE;
404 heap_free(path);
405 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
406 break;
408 case CDN_FILEOK:
409 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
410 break;
412 break;
413 default:
414 break;
416 return 0L;
420 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
422 memset(pofn, 0, sizeof(OPENFILENAMEW));
423 pofn->lStructSize = sizeof(OPENFILENAMEW);
424 pofn->hwndOwner = hWnd;
425 pofn->hInstance = hInst;
427 if (FilterBuffer[0] == 0)
429 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
430 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
432 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
433 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
434 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
435 snprintfW( FilterBuffer, MAX_PATH, filterW, filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
437 pofn->lpstrFilter = FilterBuffer;
438 pofn->nFilterIndex = 2;
439 pofn->lpstrFile = FileNameBuffer;
440 pofn->nMaxFile = _MAX_PATH;
441 pofn->lpstrFileTitle = FileTitleBuffer;
442 pofn->nMaxFileTitle = _MAX_PATH;
443 pofn->Flags = OFN_HIDEREADONLY;
444 /* some other fields may be set by the caller */
445 return TRUE;
448 static BOOL import_registry_filename(LPWSTR filename)
450 static const WCHAR rb_mode[] = {'r','b',0};
452 BOOL Success;
453 FILE* reg_file = _wfopen(filename, rb_mode);
455 if(!reg_file)
456 return FALSE;
458 Success = import_registry_file(reg_file);
460 if(fclose(reg_file) != 0)
461 Success = FALSE;
463 return Success;
466 static BOOL ImportRegistryFile(HWND hWnd)
468 OPENFILENAMEW ofn;
469 WCHAR title[128];
470 HKEY root_key = NULL;
471 WCHAR *key_path;
473 InitOpenFileName(hWnd, &ofn);
474 ofn.Flags |= OFN_ENABLESIZING;
475 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
476 ofn.lpstrTitle = title;
477 if (GetOpenFileNameW(&ofn)) {
478 if (!import_registry_filename(ofn.lpstrFile)) {
479 messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
480 return FALSE;
481 } else {
482 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
483 IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
485 } else {
486 CheckCommDlgError(hWnd);
488 RefreshTreeView(g_pChildWnd->hTreeWnd);
490 key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
491 RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
492 heap_free(key_path);
494 return TRUE;
498 static BOOL ExportRegistryFile(HWND hWnd)
500 OPENFILENAMEW ofn;
501 WCHAR title[128];
503 InitOpenFileName(hWnd, &ofn);
504 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
505 ofn.lpstrTitle = title;
506 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
507 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
508 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
509 if (GetSaveFileNameW(&ofn)) {
510 BOOL result;
511 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
512 if (!result) {
513 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
514 return FALSE;
516 } else {
517 CheckCommDlgError(hWnd);
519 return TRUE;
522 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
524 #if 1
525 PRINTDLGW pd;
527 ZeroMemory(&pd, sizeof(PRINTDLGW));
528 pd.lStructSize = sizeof(PRINTDLGW);
529 pd.hwndOwner = hWnd;
530 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
531 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
532 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
533 pd.nCopies = 1;
534 pd.nFromPage = 0xFFFF;
535 pd.nToPage = 0xFFFF;
536 pd.nMinPage = 1;
537 pd.nMaxPage = 0xFFFF;
538 if (PrintDlgW(&pd)) {
539 FIXME("printing is not yet implemented.\n");
540 /* GDI calls to render output. */
541 DeleteDC(pd.hDC); /* Delete DC when done.*/
543 #else
544 HRESULT hResult;
545 PRINTDLGEXW pd;
547 hResult = PrintDlgExW(&pd);
548 if (hResult == S_OK) {
549 switch (pd.dwResultAction) {
550 case PD_RESULT_APPLY:
551 /*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. */
552 FIXME("printing is not yet implemented.\n");
553 break;
554 case PD_RESULT_CANCEL:
555 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
556 break;
557 case PD_RESULT_PRINT:
558 FIXME("printing is not yet implemented.\n");
559 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
560 break;
561 default:
562 break;
564 } else {
565 switch (hResult) {
566 case E_OUTOFMEMORY:
567 /*Insufficient memory. */
568 break;
569 case E_INVALIDARG:
570 /* One or more arguments are invalid. */
571 break;
572 case E_POINTER:
573 /*Invalid pointer. */
574 break;
575 case E_HANDLE:
576 /*Invalid handle. */
577 break;
578 case E_FAIL:
579 /*Unspecified error. */
580 break;
581 default:
582 break;
584 return FALSE;
586 #endif
587 return TRUE;
590 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
592 BOOL result;
594 result = OpenClipboard(hWnd);
595 if (result) {
596 result = EmptyClipboard();
597 if (result) {
598 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
599 HANDLE hClipData = GlobalAlloc(GHND, len);
600 LPVOID pLoc = GlobalLock(hClipData);
601 lstrcpyW(pLoc, keyName);
602 GlobalUnlock(hClipData);
603 SetClipboardData(CF_UNICODETEXT, hClipData);
605 } else {
606 /* error emptying clipboard*/
607 /* DWORD dwError = GetLastError(); */
610 if (!CloseClipboard()) {
611 /* error closing clipboard*/
612 /* DWORD dwError = GetLastError(); */
615 } else {
616 /* error opening clipboard*/
617 /* DWORD dwError = GetLastError(); */
620 return result;
623 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
625 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
627 switch(uMsg) {
628 case WM_INITDIALOG:
629 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
630 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
631 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
632 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
633 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
634 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
635 SetWindowTextW(hwndValue, searchString);
636 return TRUE;
637 case WM_COMMAND:
638 switch(LOWORD(wParam)) {
639 case IDC_VALUE_NAME:
640 if (HIWORD(wParam) == EN_UPDATE) {
641 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
642 return TRUE;
644 break;
645 case IDOK:
646 if (GetWindowTextLengthW(hwndValue)>0) {
647 int mask = 0;
648 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
649 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
650 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
651 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
652 searchMask = mask;
653 GetWindowTextW(hwndValue, searchString, 128);
654 EndDialog(hwndDlg, IDOK);
656 return TRUE;
657 case IDCANCEL:
658 EndDialog(hwndDlg, IDCANCEL);
659 return TRUE;
661 break;
663 return FALSE;
666 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
668 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
670 switch(uMsg) {
671 case WM_INITDIALOG:
673 HTREEITEM selected;
674 TVITEMW item;
675 WCHAR buf[128];
677 selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
679 item.mask = TVIF_HANDLE | TVIF_TEXT;
680 item.hItem = selected;
681 item.pszText = buf;
682 item.cchTextMax = COUNT_OF(buf);
683 SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETITEMW, 0, (LPARAM)&item);
685 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
686 SetWindowTextW(hwndValue, buf);
687 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
688 return TRUE;
690 case WM_COMMAND:
691 switch(LOWORD(wParam)) {
692 case IDC_VALUE_NAME:
693 if (HIWORD(wParam) == EN_UPDATE) {
694 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
695 return TRUE;
697 break;
698 case IDOK:
699 if (GetWindowTextLengthW(hwndValue)>0) {
700 GetWindowTextW(hwndValue, favoriteName, 128);
701 EndDialog(hwndDlg, IDOK);
703 return TRUE;
704 case IDCANCEL:
705 EndDialog(hwndDlg, IDCANCEL);
706 return TRUE;
708 break;
710 return FALSE;
713 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
715 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
717 switch(uMsg) {
718 case WM_INITDIALOG:
719 if (!add_favourite_key_items(NULL, hwndList))
720 return FALSE;
721 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
722 return TRUE;
723 case WM_COMMAND:
724 switch(LOWORD(wParam)) {
725 case IDC_NAME_LIST:
726 if (HIWORD(wParam) == LBN_SELCHANGE) {
727 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
728 return TRUE;
730 break;
731 case IDOK: {
732 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
733 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
734 if (len>0) {
735 WCHAR *lpName = heap_xalloc((len + 1) * sizeof(WCHAR));
736 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
737 if (len>127)
738 lpName[127] = '\0';
739 lstrcpyW(favoriteName, lpName);
740 EndDialog(hwndDlg, IDOK);
741 heap_free(lpName);
743 return TRUE;
745 case IDCANCEL:
746 EndDialog(hwndDlg, IDCANCEL);
747 return TRUE;
749 break;
751 return FALSE;
754 /*******************************************************************************
756 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
758 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
761 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
763 HKEY hKeyRoot = 0;
764 DWORD valueType;
766 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
767 HKEY hKey;
768 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
769 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
770 WCHAR namebuf[KEY_MAX_LEN];
771 BYTE valuebuf[4096];
772 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
773 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
774 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
775 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
776 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
778 RegCloseKey(hKey);
780 return TRUE;
782 switch (LOWORD(wParam)) {
783 case ID_REGISTRY_IMPORTREGISTRYFILE:
784 ImportRegistryFile(hWnd);
785 break;
786 case ID_EDIT_EXPORT:
787 case ID_REGISTRY_EXPORTREGISTRYFILE:
788 ExportRegistryFile(hWnd);
789 break;
790 case ID_REGISTRY_PRINT:
792 const WCHAR empty = 0;
793 PrintRegistryHive(hWnd, &empty);
794 break;
796 case ID_EDIT_DELETE:
798 HWND hWndDelete = GetFocus();
799 if (hWndDelete == g_pChildWnd->hTreeWnd) {
800 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
801 if (keyPath == 0 || *keyPath == 0) {
802 MessageBeep(MB_ICONHAND);
803 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
804 DeleteNode(g_pChildWnd->hTreeWnd, 0);
806 heap_free(keyPath);
807 } else if (hWndDelete == g_pChildWnd->hListWnd) {
808 unsigned int num_selected, index, focus_idx;
809 WCHAR *keyPath;
811 if (!(num_selected = SendMessageW(g_pChildWnd->hListWnd, LVM_GETSELECTEDCOUNT, 0, 0L)))
812 break;
814 if (num_selected > 1)
816 if (messagebox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_VALUE_TITLE,
817 IDS_DELETE_VALUE_TEXT_MULTIPLE) != IDYES)
818 break;
821 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
823 focus_idx = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
824 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
826 while (index != -1)
828 WCHAR *valueName = GetItemText(g_pChildWnd->hListWnd, index);
829 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, num_selected == 1))
831 heap_free(valueName);
832 break;
834 heap_free(valueName);
835 SendMessageW(g_pChildWnd->hListWnd, LVM_DELETEITEM, index, 0L);
836 /* the default value item is always visible, so add it back in */
837 if (!index)
839 AddEntryToList(g_pChildWnd->hListWnd, NULL, REG_SZ, NULL, 0, 0);
840 if (!focus_idx)
842 LVITEMW item;
843 item.state = item.stateMask = LVIS_FOCUSED;
844 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
847 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
849 heap_free(keyPath);
850 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
851 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
852 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
854 break;
856 case ID_EDIT_MODIFY:
857 case ID_EDIT_MODIFY_BIN:
859 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
860 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
861 ModifyValue(hWnd, hKeyRoot, keyPath, valueName);
862 heap_free(keyPath);
863 break;
865 case ID_EDIT_FIND:
866 case ID_EDIT_FINDNEXT:
868 HTREEITEM hItem;
869 if (LOWORD(wParam) == ID_EDIT_FIND &&
870 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
871 break;
872 if (!*searchString)
873 break;
874 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
875 if (hItem) {
876 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
877 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
878 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
879 SetCursor(hcursorOld);
880 if (hItem) {
881 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
882 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
883 UpdateWindow(g_pChildWnd->hTreeWnd);
884 if (row != -1) {
885 LVITEMW item;
887 item.state = 0;
888 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
889 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
891 item.state = LVIS_FOCUSED | LVIS_SELECTED;
892 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
893 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
894 SetFocus(g_pChildWnd->hListWnd);
895 } else {
896 SetFocus(g_pChildWnd->hTreeWnd);
898 } else {
899 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
902 break;
904 case ID_EDIT_COPYKEYNAME:
906 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
907 if (fullPath) {
908 CopyKeyName(hWnd, fullPath);
909 heap_free(fullPath);
911 break;
913 case ID_EDIT_NEW_KEY:
915 WCHAR newKeyW[MAX_NEW_KEY_LEN];
916 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
917 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
918 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
919 StartKeyRename(g_pChildWnd->hTreeWnd);
921 heap_free(keyPath);
923 break;
924 case ID_EDIT_NEW_STRINGVALUE:
925 valueType = REG_SZ;
926 goto create_value;
927 case ID_EDIT_NEW_EXPANDVALUE:
928 valueType = REG_EXPAND_SZ;
929 goto create_value;
930 case ID_EDIT_NEW_MULTI_STRINGVALUE:
931 valueType = REG_MULTI_SZ;
932 goto create_value;
933 case ID_EDIT_NEW_BINARYVALUE:
934 valueType = REG_BINARY;
935 goto create_value;
936 case ID_EDIT_NEW_DWORDVALUE:
937 valueType = REG_DWORD;
938 /* fall through */
939 create_value:
941 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
942 WCHAR newKey[MAX_NEW_KEY_LEN];
943 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey))
944 StartValueRename(g_pChildWnd->hListWnd);
945 heap_free(keyPath);
947 break;
948 case ID_EDIT_RENAME:
950 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
951 if (keyPath == 0 || *keyPath == 0) {
952 MessageBeep(MB_ICONHAND);
953 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
954 StartKeyRename(g_pChildWnd->hTreeWnd);
955 } else if (GetFocus() == g_pChildWnd->hListWnd) {
956 StartValueRename(g_pChildWnd->hListWnd);
958 heap_free(keyPath);
959 break;
961 case ID_TREE_EXPAND_COLLAPSE:
963 HTREEITEM selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
964 SendMessageW(g_pChildWnd->hTreeWnd, TVM_EXPAND, TVE_TOGGLE, (LPARAM)selected);
965 break;
967 case ID_REGISTRY_PRINTERSETUP:
968 /*PRINTDLG pd;*/
969 /*PrintDlg(&pd);*/
970 /*PAGESETUPDLG psd;*/
971 /*PageSetupDlg(&psd);*/
972 break;
973 case ID_REGISTRY_OPENLOCAL:
974 break;
975 case ID_REGISTRY_EXIT:
976 DestroyWindow(hWnd);
977 break;
978 case ID_FAVORITES_ADDTOFAVORITES:
980 HKEY hKey;
981 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
982 if (lpKeyPath) {
983 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
984 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
985 0, NULL, 0,
986 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
987 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
988 RegCloseKey(hKey);
991 heap_free(lpKeyPath);
993 break;
995 case ID_FAVORITES_REMOVEFAVORITE:
997 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
998 HKEY hKey;
999 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
1000 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
1001 RegDeleteValueW(hKey, favoriteName);
1002 RegCloseKey(hKey);
1005 break;
1007 case ID_VIEW_REFRESH:
1009 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1010 RefreshTreeView(g_pChildWnd->hTreeWnd);
1011 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
1012 heap_free(keyPath);
1014 break;
1015 /*case ID_OPTIONS_TOOLBAR:*/
1016 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1017 /* break;*/
1018 case ID_VIEW_STATUSBAR:
1019 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1020 break;
1021 case ID_HELP_HELPTOPICS:
1023 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1024 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
1025 break;
1027 case ID_HELP_ABOUT:
1028 ShowAboutBox(hWnd);
1029 break;
1030 case ID_VIEW_SPLIT: {
1031 RECT rt;
1032 POINT pt, pts;
1033 GetClientRect(g_pChildWnd->hWnd, &rt);
1034 pt.x = rt.left + g_pChildWnd->nSplitPos;
1035 pt.y = (rt.bottom / 2);
1036 pts = pt;
1037 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
1038 SetCursorPos(pts.x, pts.y);
1039 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
1040 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1042 return TRUE;
1044 default:
1045 return FALSE;
1048 return TRUE;
1051 /********************************************************************************
1053 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1055 * PURPOSE: Processes messages for the main frame window.
1057 * WM_COMMAND - process the application menu
1058 * WM_DESTROY - post a quit message and return
1062 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1064 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
1066 switch (message) {
1067 case WM_CREATE:
1068 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
1069 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1070 hWnd, NULL, hInst, 0);
1071 LoadStringW(hInst, IDS_EXPAND, expandW, COUNT_OF(expandW));
1072 LoadStringW(hInst, IDS_COLLAPSE, collapseW, COUNT_OF(collapseW));
1073 LoadStringW(hInst, IDS_EDIT_MODIFY, modifyW, COUNT_OF(modifyW));
1074 LoadStringW(hInst, IDS_EDIT_MODIFY_BIN, modify_binaryW, COUNT_OF(modify_binaryW));
1075 break;
1076 case WM_COMMAND:
1077 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1078 return DefWindowProcW(hWnd, message, wParam, lParam);
1079 break;
1080 case WM_ACTIVATE:
1081 if (LOWORD(hWnd))
1082 SetFocus(g_pChildWnd->hWnd);
1083 break;
1084 case WM_SIZE:
1085 resize_frame_client(hWnd);
1086 break;
1087 case WM_TIMER:
1088 break;
1089 case WM_ENTERMENULOOP:
1090 OnEnterMenuLoop(hWnd);
1091 break;
1092 case WM_EXITMENULOOP:
1093 OnExitMenuLoop(hWnd);
1094 break;
1095 case WM_INITMENUPOPUP:
1096 if (!HIWORD(lParam))
1097 OnInitMenuPopup(hWnd, (HMENU)wParam);
1098 break;
1099 case WM_MENUSELECT:
1100 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1101 break;
1102 case WM_DESTROY:
1104 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1105 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
1106 PostQuitMessage(0);
1108 default:
1109 return DefWindowProcW(hWnd, message, wParam, lParam);
1111 return 0;