server: Cancel socket asyncs when the last handle in process is closed.
[wine.git] / programs / regedit / framewnd.c
blobc2af414d2689eb344024f396ae624326df490683
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 <shellapi.h>
29 #include "main.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
34 /********************************************************************************
35 * Global and Local Variables:
38 static const WCHAR favoritesKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
39 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
40 static WCHAR favoriteName[128];
41 static WCHAR searchString[128];
42 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
44 static WCHAR FileNameBuffer[_MAX_PATH];
45 static WCHAR FileTitleBuffer[_MAX_PATH];
46 static WCHAR FilterBuffer[_MAX_PATH];
47 static WCHAR expandW[32], collapseW[32];
48 static WCHAR modifyW[32], modify_binaryW[64];
50 /*******************************************************************************
51 * Local module support methods
54 static void resize_frame_rect(HWND hWnd, PRECT prect)
56 if (IsWindowVisible(hStatusBar)) {
57 RECT rt;
59 SetupStatusBar(hWnd, TRUE);
60 GetClientRect(hStatusBar, &rt);
61 prect->bottom -= rt.bottom;
63 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
66 static void resize_frame_client(HWND hWnd)
68 RECT rect;
70 GetClientRect(hWnd, &rect);
71 resize_frame_rect(hWnd, &rect);
74 /********************************************************************************/
76 static void OnEnterMenuLoop(HWND hWnd)
78 int nParts;
79 WCHAR empty = 0;
81 /* Update the status bar pane sizes */
82 nParts = -1;
83 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
84 bInMenuLoop = TRUE;
85 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
88 static void OnExitMenuLoop(HWND hWnd)
90 bInMenuLoop = FALSE;
91 /* Update the status bar pane sizes*/
92 SetupStatusBar(hWnd, TRUE);
93 UpdateStatusBar();
96 static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
98 TVITEMW item;
99 MENUITEMINFOW info;
101 item.hItem = selection;
102 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
103 item.stateMask = TVIS_EXPANDED;
104 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);
106 info.cbSize = sizeof(MENUITEMINFOW);
107 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
108 info.fType = MFT_STRING;
109 info.fState = MFS_ENABLED;
110 info.dwTypeData = expandW;
112 if (!item.cChildren)
114 info.fState = MFS_GRAYED;
115 goto update;
118 if (item.state & TVIS_EXPANDED)
119 info.dwTypeData = collapseW;
121 update:
122 SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
125 static void update_modify_items(HMENU hMenu, int index)
127 unsigned int state = MF_ENABLED;
129 if (index == -1)
130 state = MF_GRAYED;
132 EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
133 EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
136 static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
138 unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
140 if (!g_pChildWnd->nFocusPanel)
142 if (!keyName || !*keyName)
143 state_d = state_r = MF_GRAYED;
145 else if (index < 1)
147 state_r = MF_GRAYED;
148 if (index == -1) state_d = MF_GRAYED;
151 EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
152 EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
155 static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
157 unsigned int state = MF_ENABLED, i;
158 unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
159 ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_QWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
160 ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
162 if (!keyName)
163 state = MF_GRAYED;
165 for (i = 0; i < ARRAY_SIZE(items); i++)
166 EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
169 static void UpdateMenuItems(HMENU hMenu) {
170 HWND hwndTV = g_pChildWnd->hTreeWnd;
171 HKEY hRootKey = NULL;
172 LPWSTR keyName;
173 HTREEITEM selection;
174 int index;
176 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
177 keyName = GetItemPath(hwndTV, selection, &hRootKey);
178 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
179 MAKELPARAM(LVNI_SELECTED, 0));
181 update_expand_or_collapse_item(hwndTV, selection, hMenu);
182 update_modify_items(hMenu, index);
183 update_delete_and_rename_items(hMenu, keyName, index);
184 update_new_items_and_copy_keyname(hMenu, keyName);
185 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
186 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
187 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
189 free(keyName);
192 static void add_remove_modify_menu_items(HMENU hMenu)
194 if (!g_pChildWnd->nFocusPanel)
196 while (GetMenuItemCount(hMenu) > 9)
197 DeleteMenu(hMenu, 0, MF_BYPOSITION);
199 else if (GetMenuItemCount(hMenu) < 10)
201 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
202 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
203 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
207 static int add_favourite_key_items(HMENU hMenu, HWND hList)
209 HKEY hkey;
210 LONG rc;
211 DWORD num_values, max_value_len, value_len, type, i = 0;
212 WCHAR *value_name;
214 rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
215 if (rc != ERROR_SUCCESS) return 0;
217 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
218 &max_value_len, NULL, NULL, NULL);
219 if (rc != ERROR_SUCCESS)
221 ERR("RegQueryInfoKey failed: %ld\n", rc);
222 goto exit;
225 if (!num_values) goto exit;
227 max_value_len++;
228 value_name = malloc(max_value_len * sizeof(WCHAR));
230 if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
232 for (i = 0; i < num_values; i++)
234 value_len = max_value_len;
235 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
236 if (rc == ERROR_SUCCESS && type == REG_SZ)
238 if (hMenu)
239 AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
240 else if (hList)
241 SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
245 free(value_name);
246 exit:
247 RegCloseKey(hkey);
248 return i;
251 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
253 if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
254 add_remove_modify_menu_items(hMenu);
255 else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
257 while (GetMenuItemCount(hMenu) > 2)
258 DeleteMenu(hMenu, 2, MF_BYPOSITION);
260 add_favourite_key_items(hMenu, NULL);
263 UpdateMenuItems(hMenu);
266 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
268 WCHAR str[100];
270 str[0] = 0;
271 if (nFlags & MF_POPUP) {
272 if (hSysMenu != GetMenu(hWnd)) {
273 if (nItemID == 2) nItemID = 5;
276 if (LoadStringW(hInst, nItemID, str, 100)) {
277 /* load appropriate string*/
278 LPWSTR lpsz = str;
279 /* first newline terminates actual string*/
280 lpsz = wcschr(lpsz, '\n');
281 if (lpsz != NULL)
282 *lpsz = '\0';
284 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
287 void SetupStatusBar(HWND hWnd, BOOL bResize)
289 RECT rc;
290 int nParts;
291 GetClientRect(hWnd, &rc);
292 nParts = rc.right;
293 /* nParts = -1;*/
294 if (bResize)
295 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
296 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
297 UpdateStatusBar();
300 void UpdateStatusBar(void)
302 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
303 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
304 free(fullPath);
307 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
309 BOOL vis = IsWindowVisible(hchild);
310 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
312 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
313 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
314 resize_frame_client(hWnd);
317 static BOOL CheckCommDlgError(HWND hWnd)
319 DWORD dwErrorCode = CommDlgExtendedError();
320 switch (dwErrorCode) {
321 case CDERR_DIALOGFAILURE:
322 break;
323 case CDERR_FINDRESFAILURE:
324 break;
325 case CDERR_NOHINSTANCE:
326 break;
327 case CDERR_INITIALIZATION:
328 break;
329 case CDERR_NOHOOK:
330 break;
331 case CDERR_LOCKRESFAILURE:
332 break;
333 case CDERR_NOTEMPLATE:
334 break;
335 case CDERR_LOADRESFAILURE:
336 break;
337 case CDERR_STRUCTSIZE:
338 break;
339 case CDERR_LOADSTRFAILURE:
340 break;
341 case FNERR_BUFFERTOOSMALL:
342 break;
343 case CDERR_MEMALLOCFAILURE:
344 break;
345 case FNERR_INVALIDFILENAME:
346 break;
347 case CDERR_MEMLOCKFAILURE:
348 break;
349 case FNERR_SUBCLASSFAILURE:
350 break;
351 default:
352 break;
354 return TRUE;
357 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
359 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
361 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
362 pOpenFileName->lCustData = (LPARAM)malloc((len + 1) * sizeof(WCHAR));
363 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
365 else
367 pOpenFileName->lCustData = (LPARAM)malloc(sizeof(WCHAR));
368 *(WCHAR *)pOpenFileName->lCustData = 0;
372 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
374 static OPENFILENAMEW* pOpenFileName;
375 OFNOTIFYW *pOfNotify;
377 switch (uiMsg) {
378 case WM_INITDIALOG:
379 pOpenFileName = (OPENFILENAMEW*)lParam;
380 break;
381 case WM_COMMAND:
382 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
383 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
384 break;
385 case WM_NOTIFY:
386 pOfNotify = (OFNOTIFYW*)lParam;
387 switch (pOfNotify->hdr.code)
389 case CDN_INITDONE:
391 BOOL export_branch = FALSE;
392 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
393 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
394 if (path && path[0])
395 export_branch = TRUE;
396 free(path);
397 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
398 break;
400 case CDN_FILEOK:
401 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
402 break;
404 break;
405 default:
406 break;
408 return 0L;
412 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
414 memset(pofn, 0, sizeof(OPENFILENAMEW));
415 pofn->lStructSize = sizeof(OPENFILENAMEW);
416 pofn->hwndOwner = hWnd;
417 pofn->hInstance = hInst;
419 if (FilterBuffer[0] == 0)
421 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
423 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
424 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
425 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
426 swprintf( FilterBuffer, ARRAY_SIZE(FilterBuffer), L"%s%c*.reg%c%s%c*.reg%c%s%c*.*%c",
427 filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
429 pofn->lpstrFilter = FilterBuffer;
430 pofn->nFilterIndex = 1;
431 pofn->lpstrFile = FileNameBuffer;
432 pofn->nMaxFile = _MAX_PATH;
433 pofn->lpstrFileTitle = FileTitleBuffer;
434 pofn->nMaxFileTitle = _MAX_PATH;
435 pofn->Flags = OFN_HIDEREADONLY;
436 /* some other fields may be set by the caller */
437 return TRUE;
440 static BOOL import_registry_filename(LPWSTR filename)
442 BOOL Success;
443 FILE* reg_file = _wfopen(filename, L"rb");
445 if(!reg_file)
446 return FALSE;
448 Success = import_registry_file(reg_file);
450 if(fclose(reg_file) != 0)
451 Success = FALSE;
453 return Success;
456 static BOOL ImportRegistryFile(HWND hWnd)
458 OPENFILENAMEW ofn;
459 WCHAR title[128];
460 HKEY root_key = NULL;
461 WCHAR *key_path;
463 InitOpenFileName(hWnd, &ofn);
464 ofn.Flags |= OFN_ENABLESIZING;
465 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, ARRAY_SIZE(title));
466 ofn.lpstrTitle = title;
467 if (GetOpenFileNameW(&ofn)) {
468 if (!import_registry_filename(ofn.lpstrFile)) {
469 messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
470 return FALSE;
471 } else {
472 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
473 IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
475 } else {
476 CheckCommDlgError(hWnd);
478 RefreshTreeView(g_pChildWnd->hTreeWnd);
480 key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
481 RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
482 free(key_path);
484 return TRUE;
488 static BOOL ExportRegistryFile(HWND hWnd)
490 OPENFILENAMEW ofn;
491 WCHAR title[128];
493 InitOpenFileName(hWnd, &ofn);
494 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, ARRAY_SIZE(title));
495 ofn.lpstrTitle = title;
496 ofn.lpstrDefExt = L"reg";
497 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
498 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
499 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
500 if (GetSaveFileNameW(&ofn)) {
501 BOOL result;
502 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
503 if (!result) {
504 FIXME("Registry export failed.\n");
505 return FALSE;
507 } else {
508 CheckCommDlgError(hWnd);
510 return TRUE;
513 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
515 #if 1
516 PRINTDLGW pd;
518 ZeroMemory(&pd, sizeof(PRINTDLGW));
519 pd.lStructSize = sizeof(PRINTDLGW);
520 pd.hwndOwner = hWnd;
521 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
522 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
523 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
524 pd.nCopies = 1;
525 pd.nFromPage = 0xFFFF;
526 pd.nToPage = 0xFFFF;
527 pd.nMinPage = 1;
528 pd.nMaxPage = 0xFFFF;
529 if (PrintDlgW(&pd)) {
530 FIXME("printing is not yet implemented.\n");
531 /* GDI calls to render output. */
532 DeleteDC(pd.hDC); /* Delete DC when done.*/
534 #else
535 HRESULT hResult;
536 PRINTDLGEXW pd;
538 hResult = PrintDlgExW(&pd);
539 if (hResult == S_OK) {
540 switch (pd.dwResultAction) {
541 case PD_RESULT_APPLY:
542 /*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. */
543 FIXME("printing is not yet implemented.\n");
544 break;
545 case PD_RESULT_CANCEL:
546 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
547 break;
548 case PD_RESULT_PRINT:
549 FIXME("printing is not yet implemented.\n");
550 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
551 break;
552 default:
553 break;
555 } else {
556 switch (hResult) {
557 case E_OUTOFMEMORY:
558 /*Insufficient memory. */
559 break;
560 case E_INVALIDARG:
561 /* One or more arguments are invalid. */
562 break;
563 case E_POINTER:
564 /*Invalid pointer. */
565 break;
566 case E_HANDLE:
567 /*Invalid handle. */
568 break;
569 case E_FAIL:
570 /*Unspecified error. */
571 break;
572 default:
573 break;
575 return FALSE;
577 #endif
578 return TRUE;
581 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
583 BOOL result;
585 result = OpenClipboard(hWnd);
586 if (result) {
587 result = EmptyClipboard();
588 if (result) {
589 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
590 HANDLE hClipData = GlobalAlloc(GHND, len);
591 LPVOID pLoc = GlobalLock(hClipData);
592 lstrcpyW(pLoc, keyName);
593 GlobalUnlock(hClipData);
594 SetClipboardData(CF_UNICODETEXT, hClipData);
596 } else {
597 /* error emptying clipboard*/
598 /* DWORD dwError = GetLastError(); */
601 if (!CloseClipboard()) {
602 /* error closing clipboard*/
603 /* DWORD dwError = GetLastError(); */
606 } else {
607 /* error opening clipboard*/
608 /* DWORD dwError = GetLastError(); */
611 return result;
614 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
616 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
618 switch(uMsg) {
619 case WM_INITDIALOG:
620 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
621 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
622 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
623 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
624 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
625 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
626 SetWindowTextW(hwndValue, searchString);
627 return TRUE;
628 case WM_COMMAND:
629 switch(LOWORD(wParam)) {
630 case IDC_VALUE_NAME:
631 if (HIWORD(wParam) == EN_UPDATE) {
632 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
633 return TRUE;
635 break;
636 case IDOK:
637 if (GetWindowTextLengthW(hwndValue)>0) {
638 int mask = 0;
639 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
640 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
641 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
642 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
643 searchMask = mask;
644 GetWindowTextW(hwndValue, searchString, 128);
645 EndDialog(hwndDlg, IDOK);
647 return TRUE;
648 case IDCANCEL:
649 EndDialog(hwndDlg, IDCANCEL);
650 return TRUE;
652 break;
654 return FALSE;
657 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
659 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
661 switch(uMsg) {
662 case WM_INITDIALOG:
664 HTREEITEM selected;
665 TVITEMW item;
666 WCHAR buf[128];
668 selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
670 item.mask = TVIF_HANDLE | TVIF_TEXT;
671 item.hItem = selected;
672 item.pszText = buf;
673 item.cchTextMax = ARRAY_SIZE(buf);
674 SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETITEMW, 0, (LPARAM)&item);
676 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
677 SetWindowTextW(hwndValue, buf);
678 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
679 return TRUE;
681 case WM_COMMAND:
682 switch(LOWORD(wParam)) {
683 case IDC_VALUE_NAME:
684 if (HIWORD(wParam) == EN_UPDATE) {
685 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
686 return TRUE;
688 break;
689 case IDOK:
690 if (GetWindowTextLengthW(hwndValue)>0) {
691 GetWindowTextW(hwndValue, favoriteName, 128);
692 EndDialog(hwndDlg, IDOK);
694 return TRUE;
695 case IDCANCEL:
696 EndDialog(hwndDlg, IDCANCEL);
697 return TRUE;
699 break;
701 return FALSE;
704 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
706 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
708 switch(uMsg) {
709 case WM_INITDIALOG:
710 if (!add_favourite_key_items(NULL, hwndList))
711 return FALSE;
712 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
713 return TRUE;
714 case WM_COMMAND:
715 switch(LOWORD(wParam)) {
716 case IDC_NAME_LIST:
717 if (HIWORD(wParam) == LBN_SELCHANGE) {
718 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
719 return TRUE;
721 break;
722 case IDOK: {
723 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
724 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
725 if (len>0) {
726 WCHAR *lpName = malloc((len + 1) * sizeof(WCHAR));
727 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
728 if (len>127)
729 lpName[127] = '\0';
730 lstrcpyW(favoriteName, lpName);
731 EndDialog(hwndDlg, IDOK);
732 free(lpName);
734 return TRUE;
736 case IDCANCEL:
737 EndDialog(hwndDlg, IDCANCEL);
738 return TRUE;
740 break;
742 return FALSE;
745 /*******************************************************************************
747 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
749 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
752 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
754 HKEY hKeyRoot = 0;
755 DWORD valueType;
757 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
758 HKEY hKey;
759 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
760 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
761 WCHAR namebuf[KEY_MAX_LEN];
762 BYTE valuebuf[4096];
763 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
764 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
765 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
766 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
767 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
769 RegCloseKey(hKey);
771 return TRUE;
773 switch (LOWORD(wParam)) {
774 case ID_REGISTRY_IMPORTREGISTRYFILE:
775 ImportRegistryFile(hWnd);
776 break;
777 case ID_EDIT_EXPORT:
778 case ID_REGISTRY_EXPORTREGISTRYFILE:
779 ExportRegistryFile(hWnd);
780 break;
781 case ID_REGISTRY_PRINT:
783 const WCHAR empty = 0;
784 PrintRegistryHive(hWnd, &empty);
785 break;
787 case ID_EDIT_DELETE:
789 HWND hWndDelete = GetFocus();
790 if (hWndDelete == g_pChildWnd->hTreeWnd) {
791 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
792 if (keyPath == 0 || *keyPath == 0) {
793 MessageBeep(MB_ICONHAND);
794 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
795 DeleteNode(g_pChildWnd->hTreeWnd, 0);
797 free(keyPath);
798 } else if (hWndDelete == g_pChildWnd->hListWnd) {
799 unsigned int num_selected, index, focus_idx;
800 WCHAR *keyPath;
802 num_selected = SendMessageW(g_pChildWnd->hListWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
804 if (!num_selected)
805 break;
806 else if (num_selected == 1)
807 index = IDS_DELETE_VALUE_TEXT;
808 else
809 index = IDS_DELETE_VALUE_TEXT_MULTIPLE;
811 if (messagebox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_VALUE_TITLE, index) != IDYES)
812 break;
814 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
816 focus_idx = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
817 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
819 while (index != -1)
821 WCHAR *valueName = GetItemText(g_pChildWnd->hListWnd, index);
822 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
824 free(valueName);
825 break;
827 free(valueName);
828 SendMessageW(g_pChildWnd->hListWnd, LVM_DELETEITEM, index, 0L);
829 /* the default value item is always visible, so add it back in */
830 if (!index)
832 AddEntryToList(g_pChildWnd->hListWnd, NULL, REG_SZ, NULL, 0, 0);
833 if (!focus_idx)
835 LVITEMW item;
836 item.state = item.stateMask = LVIS_FOCUSED;
837 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
840 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
842 free(keyPath);
843 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
844 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
845 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
847 break;
849 case ID_EDIT_MODIFY:
850 case ID_EDIT_MODIFY_BIN:
852 WCHAR *valueName = GetValueName(g_pChildWnd->hListWnd);
853 WCHAR *keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
854 ModifyValue(hWnd, hKeyRoot, keyPath, valueName);
855 free(keyPath);
856 free(valueName);
857 break;
859 case ID_EDIT_FIND:
860 case ID_EDIT_FINDNEXT:
862 HTREEITEM hItem;
863 if (LOWORD(wParam) == ID_EDIT_FIND &&
864 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
865 break;
866 if (!*searchString)
867 break;
868 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
869 if (hItem) {
870 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
871 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
872 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
873 SetCursor(hcursorOld);
874 if (hItem) {
875 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
876 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
877 UpdateWindow(g_pChildWnd->hTreeWnd);
878 if (row != -1) {
879 LVITEMW item;
881 item.state = 0;
882 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
883 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
885 item.state = LVIS_FOCUSED | LVIS_SELECTED;
886 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
887 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
888 SetFocus(g_pChildWnd->hListWnd);
889 } else {
890 SetFocus(g_pChildWnd->hTreeWnd);
892 } else {
893 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
896 break;
898 case ID_EDIT_COPYKEYNAME:
900 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
901 if (fullPath) {
902 CopyKeyName(hWnd, fullPath);
903 free(fullPath);
905 break;
907 case ID_EDIT_NEW_KEY:
909 WCHAR newKeyW[MAX_NEW_KEY_LEN];
910 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
911 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
912 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
913 StartKeyRename(g_pChildWnd->hTreeWnd);
915 free(keyPath);
917 break;
918 case ID_EDIT_NEW_STRINGVALUE:
919 valueType = REG_SZ;
920 goto create_value;
921 case ID_EDIT_NEW_EXPANDVALUE:
922 valueType = REG_EXPAND_SZ;
923 goto create_value;
924 case ID_EDIT_NEW_MULTI_STRINGVALUE:
925 valueType = REG_MULTI_SZ;
926 goto create_value;
927 case ID_EDIT_NEW_BINARYVALUE:
928 valueType = REG_BINARY;
929 goto create_value;
930 case ID_EDIT_NEW_DWORDVALUE:
931 valueType = REG_DWORD;
932 goto create_value;
933 case ID_EDIT_NEW_QWORDVALUE:
934 valueType = REG_QWORD;
935 /* fall through */
936 create_value:
938 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
939 WCHAR newKey[MAX_NEW_KEY_LEN];
940 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey))
941 StartValueRename(g_pChildWnd->hListWnd);
942 free(keyPath);
944 break;
945 case ID_EDIT_RENAME:
947 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
948 if (!keyPath) {
949 MessageBeep(MB_ICONHAND);
950 break;
951 } else if (*keyPath && GetFocus() == g_pChildWnd->hTreeWnd) {
952 StartKeyRename(g_pChildWnd->hTreeWnd);
953 } else if (GetFocus() == g_pChildWnd->hListWnd) {
954 StartValueRename(g_pChildWnd->hListWnd);
956 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 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 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 WinHelpW(hWnd, L"regedit", HELP_FINDER, 0);
1022 break;
1024 case ID_HELP_ABOUT:
1025 ShowAboutBox(hWnd);
1026 break;
1027 case ID_VIEW_SPLIT: {
1028 RECT rt;
1029 POINT pt, pts;
1030 GetClientRect(g_pChildWnd->hWnd, &rt);
1031 pt.x = rt.left + g_pChildWnd->nSplitPos;
1032 pt.y = (rt.bottom / 2);
1033 pts = pt;
1034 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
1035 SetCursorPos(pts.x, pts.y);
1036 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
1037 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1039 return TRUE;
1041 default:
1042 return FALSE;
1045 return TRUE;
1048 /********************************************************************************
1050 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1052 * PURPOSE: Processes messages for the main frame window.
1054 * WM_COMMAND - process the application menu
1055 * WM_DESTROY - post a quit message and return
1059 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1061 switch (message) {
1062 case WM_CREATE:
1063 CreateWindowExW(0, szChildClass, L"regedit child window", WS_CHILD | WS_VISIBLE,
1064 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1065 hWnd, NULL, hInst, 0);
1066 LoadStringW(hInst, IDS_EXPAND, expandW, ARRAY_SIZE(expandW));
1067 LoadStringW(hInst, IDS_COLLAPSE, collapseW, ARRAY_SIZE(collapseW));
1068 LoadStringW(hInst, IDS_EDIT_MODIFY, modifyW, ARRAY_SIZE(modifyW));
1069 LoadStringW(hInst, IDS_EDIT_MODIFY_BIN, modify_binaryW, ARRAY_SIZE(modify_binaryW));
1070 break;
1071 case WM_COMMAND:
1072 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1073 return DefWindowProcW(hWnd, message, wParam, lParam);
1074 break;
1075 case WM_ACTIVATE:
1076 if (LOWORD(hWnd))
1077 SetFocus(g_pChildWnd->hWnd);
1078 break;
1079 case WM_SIZE:
1080 resize_frame_client(hWnd);
1081 break;
1082 case WM_TIMER:
1083 break;
1084 case WM_ENTERMENULOOP:
1085 OnEnterMenuLoop(hWnd);
1086 break;
1087 case WM_EXITMENULOOP:
1088 OnExitMenuLoop(hWnd);
1089 break;
1090 case WM_INITMENUPOPUP:
1091 if (!HIWORD(lParam))
1092 OnInitMenuPopup(hWnd, (HMENU)wParam);
1093 break;
1094 case WM_MENUSELECT:
1095 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1096 break;
1097 case WM_DESTROY:
1099 WinHelpW(hWnd, L"regedit", HELP_QUIT, 0);
1100 PostQuitMessage(0);
1102 default:
1103 return DefWindowProcW(hWnd, message, wParam, lParam);
1105 return 0;