webservices: Increase the maximum size of the channel writer buffer.
[wine.git] / programs / regedit / framewnd.c
blob4d828c0e7cfe25a8d8c87500e43173b7ea649d0a
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"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
37 /********************************************************************************
38 * Global and Local Variables:
41 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};
42 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
43 static WCHAR favoriteName[128];
44 static WCHAR searchString[128];
45 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
47 static WCHAR FileNameBuffer[_MAX_PATH];
48 static WCHAR FileTitleBuffer[_MAX_PATH];
49 static WCHAR FilterBuffer[_MAX_PATH];
50 static WCHAR expandW[32], collapseW[32];
51 static WCHAR modifyW[32], modify_binaryW[64];
53 /*******************************************************************************
54 * Local module support methods
57 static void resize_frame_rect(HWND hWnd, PRECT prect)
59 if (IsWindowVisible(hStatusBar)) {
60 RECT rt;
62 SetupStatusBar(hWnd, TRUE);
63 GetClientRect(hStatusBar, &rt);
64 prect->bottom -= rt.bottom;
66 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
69 static void resize_frame_client(HWND hWnd)
71 RECT rect;
73 GetClientRect(hWnd, &rect);
74 resize_frame_rect(hWnd, &rect);
77 /********************************************************************************/
79 static void OnEnterMenuLoop(HWND hWnd)
81 int nParts;
82 WCHAR empty = 0;
84 /* Update the status bar pane sizes */
85 nParts = -1;
86 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
87 bInMenuLoop = TRUE;
88 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
91 static void OnExitMenuLoop(HWND hWnd)
93 bInMenuLoop = FALSE;
94 /* Update the status bar pane sizes*/
95 SetupStatusBar(hWnd, TRUE);
96 UpdateStatusBar();
99 static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
101 TVITEMW item;
102 MENUITEMINFOW info;
104 item.hItem = selection;
105 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
106 item.stateMask = TVIS_EXPANDED;
107 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);
109 info.cbSize = sizeof(MENUITEMINFOW);
110 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
111 info.fType = MFT_STRING;
112 info.fState = MFS_ENABLED;
113 info.dwTypeData = expandW;
115 if (!item.cChildren)
117 info.fState = MFS_GRAYED;
118 goto update;
121 if (item.state & TVIS_EXPANDED)
122 info.dwTypeData = collapseW;
124 update:
125 SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
128 static void update_modify_items(HMENU hMenu, int index)
130 unsigned int state = MF_ENABLED;
132 if (index == -1)
133 state = MF_GRAYED;
135 EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
136 EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
139 static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
141 unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
143 if (!g_pChildWnd->nFocusPanel)
145 if (!keyName || !*keyName)
146 state_d = state_r = MF_GRAYED;
148 else if (index < 1)
150 state_r = MF_GRAYED;
151 if (index == -1) state_d = MF_GRAYED;
154 EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
155 EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
158 static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
160 unsigned int state = MF_ENABLED, i;
161 unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
162 ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
163 ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
165 if (!keyName)
166 state = MF_GRAYED;
168 for (i = 0; i < ARRAY_SIZE(items); i++)
169 EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
172 static void UpdateMenuItems(HMENU hMenu) {
173 HWND hwndTV = g_pChildWnd->hTreeWnd;
174 HKEY hRootKey = NULL;
175 LPWSTR keyName;
176 HTREEITEM selection;
177 int index;
179 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
180 keyName = GetItemPath(hwndTV, selection, &hRootKey);
181 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
182 MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
184 update_expand_or_collapse_item(hwndTV, selection, hMenu);
185 update_modify_items(hMenu, index);
186 update_delete_and_rename_items(hMenu, keyName, index);
187 update_new_items_and_copy_keyname(hMenu, keyName);
188 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
189 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
190 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
192 heap_free(keyName);
195 static void add_remove_modify_menu_items(HMENU hMenu)
197 if (!g_pChildWnd->nFocusPanel)
199 while (GetMenuItemCount(hMenu) > 9)
200 DeleteMenu(hMenu, 0, MF_BYPOSITION);
202 else if (GetMenuItemCount(hMenu) < 10)
204 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
205 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
206 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
210 static int add_favourite_key_items(HMENU hMenu, HWND hList)
212 HKEY hkey;
213 LONG rc;
214 DWORD num_values, max_value_len, value_len, type, i = 0;
215 WCHAR *value_name;
217 rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
218 if (rc != ERROR_SUCCESS) return 0;
220 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
221 &max_value_len, NULL, NULL, NULL);
222 if (rc != ERROR_SUCCESS)
224 ERR("RegQueryInfoKey failed: %d\n", rc);
225 goto exit;
228 if (!num_values) goto exit;
230 max_value_len++;
231 value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
233 if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
235 for (i = 0; i < num_values; i++)
237 value_len = max_value_len;
238 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
239 if (rc == ERROR_SUCCESS && type == REG_SZ)
241 if (hMenu)
242 AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
243 else if (hList)
244 SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
248 heap_free(value_name);
249 exit:
250 RegCloseKey(hkey);
251 return i;
254 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
256 if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
257 add_remove_modify_menu_items(hMenu);
258 else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
260 while (GetMenuItemCount(hMenu) > 2)
261 DeleteMenu(hMenu, 2, MF_BYPOSITION);
263 add_favourite_key_items(hMenu, NULL);
266 UpdateMenuItems(hMenu);
269 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
271 WCHAR str[100];
273 str[0] = 0;
274 if (nFlags & MF_POPUP) {
275 if (hSysMenu != GetMenu(hWnd)) {
276 if (nItemID == 2) nItemID = 5;
279 if (LoadStringW(hInst, nItemID, str, 100)) {
280 /* load appropriate string*/
281 LPWSTR lpsz = str;
282 /* first newline terminates actual string*/
283 lpsz = strchrW(lpsz, '\n');
284 if (lpsz != NULL)
285 *lpsz = '\0';
287 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
290 void SetupStatusBar(HWND hWnd, BOOL bResize)
292 RECT rc;
293 int nParts;
294 GetClientRect(hWnd, &rc);
295 nParts = rc.right;
296 /* nParts = -1;*/
297 if (bResize)
298 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
299 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
300 UpdateStatusBar();
303 void UpdateStatusBar(void)
305 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
306 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
307 heap_free(fullPath);
310 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
312 BOOL vis = IsWindowVisible(hchild);
313 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
315 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
316 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
317 resize_frame_client(hWnd);
320 static BOOL CheckCommDlgError(HWND hWnd)
322 DWORD dwErrorCode = CommDlgExtendedError();
323 switch (dwErrorCode) {
324 case CDERR_DIALOGFAILURE:
325 break;
326 case CDERR_FINDRESFAILURE:
327 break;
328 case CDERR_NOHINSTANCE:
329 break;
330 case CDERR_INITIALIZATION:
331 break;
332 case CDERR_NOHOOK:
333 break;
334 case CDERR_LOCKRESFAILURE:
335 break;
336 case CDERR_NOTEMPLATE:
337 break;
338 case CDERR_LOADRESFAILURE:
339 break;
340 case CDERR_STRUCTSIZE:
341 break;
342 case CDERR_LOADSTRFAILURE:
343 break;
344 case FNERR_BUFFERTOOSMALL:
345 break;
346 case CDERR_MEMALLOCFAILURE:
347 break;
348 case FNERR_INVALIDFILENAME:
349 break;
350 case CDERR_MEMLOCKFAILURE:
351 break;
352 case FNERR_SUBCLASSFAILURE:
353 break;
354 default:
355 break;
357 return TRUE;
360 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
362 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
364 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
365 pOpenFileName->lCustData = (LPARAM)heap_xalloc((len + 1) * sizeof(WCHAR));
366 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
368 else
370 pOpenFileName->lCustData = (LPARAM)heap_xalloc(sizeof(WCHAR));
371 *(WCHAR *)pOpenFileName->lCustData = 0;
375 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
377 static OPENFILENAMEW* pOpenFileName;
378 OFNOTIFYW *pOfNotify;
380 switch (uiMsg) {
381 case WM_INITDIALOG:
382 pOpenFileName = (OPENFILENAMEW*)lParam;
383 break;
384 case WM_COMMAND:
385 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
386 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
387 break;
388 case WM_NOTIFY:
389 pOfNotify = (OFNOTIFYW*)lParam;
390 switch (pOfNotify->hdr.code)
392 case CDN_INITDONE:
394 BOOL export_branch = FALSE;
395 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
396 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
397 if (path && path[0])
398 export_branch = TRUE;
399 heap_free(path);
400 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
401 break;
403 case CDN_FILEOK:
404 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
405 break;
407 break;
408 default:
409 break;
411 return 0L;
415 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
417 memset(pofn, 0, sizeof(OPENFILENAMEW));
418 pofn->lStructSize = sizeof(OPENFILENAMEW);
419 pofn->hwndOwner = hWnd;
420 pofn->hInstance = hInst;
422 if (FilterBuffer[0] == 0)
424 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
425 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
427 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
428 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
429 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
430 snprintfW( FilterBuffer, MAX_PATH, filterW, 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;