advapi32/tests: Fix copy&paste typo.
[wine.git] / programs / regedit / framewnd.c
blob2e2867024a7312cc6ae7c68fb17bd98535c46fe5
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 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];
52 /*******************************************************************************
53 * Local module support methods
56 static void resize_frame_rect(HWND hWnd, PRECT prect)
58 RECT rt;
60 if (IsWindowVisible(hToolBar)) {
61 SendMessageW(hToolBar, WM_SIZE, 0, 0);
62 GetClientRect(hToolBar, &rt);
63 prect->top = rt.bottom+3;
64 prect->bottom -= rt.bottom+3;
67 if (IsWindowVisible(hStatusBar)) {
68 SetupStatusBar(hWnd, TRUE);
69 GetClientRect(hStatusBar, &rt);
70 prect->bottom -= rt.bottom;
72 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
75 static void resize_frame_client(HWND hWnd)
77 RECT rect;
79 GetClientRect(hWnd, &rect);
80 resize_frame_rect(hWnd, &rect);
83 /********************************************************************************/
85 static void OnEnterMenuLoop(HWND hWnd)
87 int nParts;
88 WCHAR empty = 0;
90 /* Update the status bar pane sizes */
91 nParts = -1;
92 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
93 bInMenuLoop = TRUE;
94 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
97 static void OnExitMenuLoop(HWND hWnd)
99 bInMenuLoop = FALSE;
100 /* Update the status bar pane sizes*/
101 SetupStatusBar(hWnd, TRUE);
102 UpdateStatusBar();
105 static void UpdateMenuItems(HMENU hMenu) {
106 HWND hwndTV = g_pChildWnd->hTreeWnd;
107 BOOL bAllowEdit = FALSE;
108 HKEY hRootKey = NULL;
109 LPWSTR keyName;
110 HTREEITEM selection;
112 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
113 keyName = GetItemPath(hwndTV, selection, &hRootKey);
114 if (GetFocus() != hwndTV || (keyName && *keyName)) { /* can't modify root keys, but allow for their values */
115 bAllowEdit = TRUE;
117 EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
118 EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
119 EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
120 EnableMenuItem(hMenu, ID_EDIT_DELETE, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
121 EnableMenuItem(hMenu, ID_EDIT_RENAME, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
122 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
123 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
124 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
126 HeapFree(GetProcessHeap(), 0, keyName);
129 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
131 if (wItem == 3) {
132 HKEY hKey;
133 while(GetMenuItemCount(hMenu)>2)
134 DeleteMenu(hMenu, 2, MF_BYPOSITION);
135 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
136 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
137 WCHAR namebuf[KEY_MAX_LEN];
138 BYTE valuebuf[4096];
139 int i = 0;
140 BOOL sep = FALSE;
141 DWORD ksize, vsize, type;
142 LONG error;
143 do {
144 ksize = KEY_MAX_LEN;
145 vsize = sizeof(valuebuf);
146 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
147 if (error != ERROR_SUCCESS)
148 break;
149 if (type == REG_SZ) {
150 if (!sep) {
151 AppendMenuW(hMenu, MF_SEPARATOR, -1, NULL);
152 sep = TRUE;
154 AppendMenuW(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
156 i++;
157 } while(error == ERROR_SUCCESS);
158 RegCloseKey(hKey);
161 UpdateMenuItems(hMenu);
164 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
166 WCHAR str[100];
168 str[0] = 0;
169 if (nFlags & MF_POPUP) {
170 if (hSysMenu != GetMenu(hWnd)) {
171 if (nItemID == 2) nItemID = 5;
174 if (LoadStringW(hInst, nItemID, str, 100)) {
175 /* load appropriate string*/
176 LPWSTR lpsz = str;
177 /* first newline terminates actual string*/
178 lpsz = strchrW(lpsz, '\n');
179 if (lpsz != NULL)
180 *lpsz = '\0';
182 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
185 void SetupStatusBar(HWND hWnd, BOOL bResize)
187 RECT rc;
188 int nParts;
189 GetClientRect(hWnd, &rc);
190 nParts = rc.right;
191 /* nParts = -1;*/
192 if (bResize)
193 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
194 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
195 UpdateStatusBar();
198 void UpdateStatusBar(void)
200 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
201 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
202 HeapFree(GetProcessHeap(), 0, fullPath);
205 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
207 BOOL vis = IsWindowVisible(hchild);
208 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
210 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
211 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
212 resize_frame_client(hWnd);
215 static BOOL CheckCommDlgError(HWND hWnd)
217 DWORD dwErrorCode = CommDlgExtendedError();
218 switch (dwErrorCode) {
219 case CDERR_DIALOGFAILURE:
220 break;
221 case CDERR_FINDRESFAILURE:
222 break;
223 case CDERR_NOHINSTANCE:
224 break;
225 case CDERR_INITIALIZATION:
226 break;
227 case CDERR_NOHOOK:
228 break;
229 case CDERR_LOCKRESFAILURE:
230 break;
231 case CDERR_NOTEMPLATE:
232 break;
233 case CDERR_LOADRESFAILURE:
234 break;
235 case CDERR_STRUCTSIZE:
236 break;
237 case CDERR_LOADSTRFAILURE:
238 break;
239 case FNERR_BUFFERTOOSMALL:
240 break;
241 case CDERR_MEMALLOCFAILURE:
242 break;
243 case FNERR_INVALIDFILENAME:
244 break;
245 case CDERR_MEMLOCKFAILURE:
246 break;
247 case FNERR_SUBCLASSFAILURE:
248 break;
249 default:
250 break;
252 return TRUE;
255 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
257 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
259 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
260 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
261 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
263 else
264 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
267 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
269 static OPENFILENAMEW* pOpenFileName;
270 OFNOTIFYW *pOfNotify;
272 switch (uiMsg) {
273 case WM_INITDIALOG:
274 pOpenFileName = (OPENFILENAMEW*)lParam;
275 break;
276 case WM_COMMAND:
277 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
278 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
279 break;
280 case WM_NOTIFY:
281 pOfNotify = (OFNOTIFYW*)lParam;
282 switch (pOfNotify->hdr.code)
284 case CDN_INITDONE:
286 BOOL export_branch = FALSE;
287 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
288 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
289 if (path && strlenW(path) > 0)
290 export_branch = TRUE;
291 HeapFree(GetProcessHeap(), 0, path);
292 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
293 break;
295 case CDN_FILEOK:
296 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
297 break;
299 break;
300 default:
301 break;
303 return 0L;
307 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
309 memset(pofn, 0, sizeof(OPENFILENAMEW));
310 pofn->lStructSize = sizeof(OPENFILENAMEW);
311 pofn->hwndOwner = hWnd;
312 pofn->hInstance = hInst;
314 if (FilterBuffer[0] == 0)
316 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
317 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
319 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
320 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
321 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
322 snprintfW( FilterBuffer, MAX_PATH, filterW, filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
324 pofn->lpstrFilter = FilterBuffer;
325 pofn->nFilterIndex = 2;
326 pofn->lpstrFile = FileNameBuffer;
327 pofn->nMaxFile = _MAX_PATH;
328 pofn->lpstrFileTitle = FileTitleBuffer;
329 pofn->nMaxFileTitle = _MAX_PATH;
330 pofn->Flags = OFN_HIDEREADONLY;
331 /* some other fields may be set by the caller */
332 return TRUE;
335 static BOOL import_registry_filename(LPWSTR filename)
337 static const WCHAR mode_r[] = {'r',0};
339 BOOL Success;
340 FILE* reg_file = _wfopen(filename, mode_r);
342 if(!reg_file)
343 return FALSE;
345 Success = import_registry_file(reg_file);
347 if(fclose(reg_file) != 0)
348 Success = FALSE;
350 return Success;
353 static BOOL ImportRegistryFile(HWND hWnd)
355 OPENFILENAMEW ofn;
356 WCHAR title[128];
358 InitOpenFileName(hWnd, &ofn);
359 ofn.Flags |= OFN_ENABLESIZING;
360 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
361 ofn.lpstrTitle = title;
362 if (GetOpenFileNameW(&ofn)) {
363 if (!import_registry_filename(ofn.lpstrFile))
364 return FALSE;
365 } else {
366 CheckCommDlgError(hWnd);
368 RefreshTreeView(g_pChildWnd->hTreeWnd);
369 return TRUE;
373 static BOOL ExportRegistryFile(HWND hWnd)
375 OPENFILENAMEW ofn;
376 WCHAR title[128];
378 InitOpenFileName(hWnd, &ofn);
379 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
380 ofn.lpstrTitle = title;
381 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
382 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
383 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
384 if (GetSaveFileNameW(&ofn)) {
385 BOOL result;
386 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
387 if (!result) {
388 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
389 return FALSE;
391 } else {
392 CheckCommDlgError(hWnd);
394 return TRUE;
397 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
399 #if 1
400 PRINTDLGW pd;
402 ZeroMemory(&pd, sizeof(PRINTDLGW));
403 pd.lStructSize = sizeof(PRINTDLGW);
404 pd.hwndOwner = hWnd;
405 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
406 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
407 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
408 pd.nCopies = 1;
409 pd.nFromPage = 0xFFFF;
410 pd.nToPage = 0xFFFF;
411 pd.nMinPage = 1;
412 pd.nMaxPage = 0xFFFF;
413 if (PrintDlgW(&pd)) {
414 FIXME("printing is not yet implemented.\n");
415 /* GDI calls to render output. */
416 DeleteDC(pd.hDC); /* Delete DC when done.*/
418 #else
419 HRESULT hResult;
420 PRINTDLGEXW pd;
422 hResult = PrintDlgExW(&pd);
423 if (hResult == S_OK) {
424 switch (pd.dwResultAction) {
425 case PD_RESULT_APPLY:
426 /*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. */
427 FIXME("printing is not yet implemented.\n");
428 break;
429 case PD_RESULT_CANCEL:
430 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
431 break;
432 case PD_RESULT_PRINT:
433 FIXME("printing is not yet implemented.\n");
434 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
435 break;
436 default:
437 break;
439 } else {
440 switch (hResult) {
441 case E_OUTOFMEMORY:
442 /*Insufficient memory. */
443 break;
444 case E_INVALIDARG:
445 /* One or more arguments are invalid. */
446 break;
447 case E_POINTER:
448 /*Invalid pointer. */
449 break;
450 case E_HANDLE:
451 /*Invalid handle. */
452 break;
453 case E_FAIL:
454 /*Unspecified error. */
455 break;
456 default:
457 break;
459 return FALSE;
461 #endif
462 return TRUE;
465 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
467 BOOL result;
469 result = OpenClipboard(hWnd);
470 if (result) {
471 result = EmptyClipboard();
472 if (result) {
473 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
474 HANDLE hClipData = GlobalAlloc(GHND, len);
475 LPVOID pLoc = GlobalLock(hClipData);
476 lstrcpyW(pLoc, keyName);
477 GlobalUnlock(hClipData);
478 hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
480 } else {
481 /* error emptying clipboard*/
482 /* DWORD dwError = GetLastError(); */
485 if (!CloseClipboard()) {
486 /* error closing clipboard*/
487 /* DWORD dwError = GetLastError(); */
490 } else {
491 /* error opening clipboard*/
492 /* DWORD dwError = GetLastError(); */
495 return result;
498 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
500 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
502 switch(uMsg) {
503 case WM_INITDIALOG:
504 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
505 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
506 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
507 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
508 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
509 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
510 SetWindowTextW(hwndValue, searchString);
511 return TRUE;
512 case WM_COMMAND:
513 switch(LOWORD(wParam)) {
514 case IDC_VALUE_NAME:
515 if (HIWORD(wParam) == EN_UPDATE) {
516 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
517 return TRUE;
519 break;
520 case IDOK:
521 if (GetWindowTextLengthW(hwndValue)>0) {
522 int mask = 0;
523 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
524 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
525 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
526 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
527 searchMask = mask;
528 GetWindowTextW(hwndValue, searchString, 128);
529 EndDialog(hwndDlg, IDOK);
531 return TRUE;
532 case IDCANCEL:
533 EndDialog(hwndDlg, IDCANCEL);
534 return TRUE;
536 break;
538 return FALSE;
541 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
543 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
545 switch(uMsg) {
546 case WM_INITDIALOG:
548 HKEY hKeyRoot = NULL;
549 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
551 if(!ItemPath || !*ItemPath)
552 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
553 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
554 SetWindowTextW(hwndValue, ItemPath);
555 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
556 HeapFree(GetProcessHeap(), 0, ItemPath);
557 return TRUE;
559 case WM_COMMAND:
560 switch(LOWORD(wParam)) {
561 case IDC_VALUE_NAME:
562 if (HIWORD(wParam) == EN_UPDATE) {
563 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
564 return TRUE;
566 break;
567 case IDOK:
568 if (GetWindowTextLengthW(hwndValue)>0) {
569 GetWindowTextW(hwndValue, favoriteName, 128);
570 EndDialog(hwndDlg, IDOK);
572 return TRUE;
573 case IDCANCEL:
574 EndDialog(hwndDlg, IDCANCEL);
575 return TRUE;
577 break;
579 return FALSE;
582 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
584 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
586 switch(uMsg) {
587 case WM_INITDIALOG: {
588 HKEY hKey;
589 int i = 0;
590 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
591 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
592 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
593 WCHAR namebuf[KEY_MAX_LEN];
594 BYTE valuebuf[4096];
595 DWORD ksize, vsize, type;
596 LONG error;
597 do {
598 ksize = KEY_MAX_LEN;
599 vsize = sizeof(valuebuf);
600 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
601 if (error != ERROR_SUCCESS)
602 break;
603 if (type == REG_SZ) {
604 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
606 i++;
607 } while(error == ERROR_SUCCESS);
608 RegCloseKey(hKey);
610 else
611 return FALSE;
612 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
613 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
614 return TRUE;
616 case WM_COMMAND:
617 switch(LOWORD(wParam)) {
618 case IDC_NAME_LIST:
619 if (HIWORD(wParam) == LBN_SELCHANGE) {
620 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
621 return TRUE;
623 break;
624 case IDOK: {
625 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
626 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
627 if (len>0) {
628 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
629 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
630 if (len>127)
631 lpName[127] = '\0';
632 lstrcpyW(favoriteName, lpName);
633 EndDialog(hwndDlg, IDOK);
634 HeapFree(GetProcessHeap(), 0, lpName);
636 return TRUE;
638 case IDCANCEL:
639 EndDialog(hwndDlg, IDCANCEL);
640 return TRUE;
642 break;
644 return FALSE;
647 /*******************************************************************************
649 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
651 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
654 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
656 HKEY hKeyRoot = 0;
657 DWORD valueType;
658 int curIndex;
659 BOOL firstItem = TRUE;
661 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
662 HKEY hKey;
663 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
664 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
665 WCHAR namebuf[KEY_MAX_LEN];
666 BYTE valuebuf[4096];
667 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
668 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
669 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
670 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
671 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
673 RegCloseKey(hKey);
675 return TRUE;
677 switch (LOWORD(wParam)) {
678 case ID_REGISTRY_IMPORTREGISTRYFILE:
679 ImportRegistryFile(hWnd);
680 break;
681 case ID_EDIT_EXPORT:
682 case ID_REGISTRY_EXPORTREGISTRYFILE:
683 ExportRegistryFile(hWnd);
684 break;
685 case ID_REGISTRY_PRINT:
687 const WCHAR empty = 0;
688 PrintRegistryHive(hWnd, &empty);
689 break;
691 case ID_EDIT_DELETE:
693 HWND hWndDelete = GetFocus();
694 if (hWndDelete == g_pChildWnd->hTreeWnd) {
695 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
696 if (keyPath == 0 || *keyPath == 0) {
697 MessageBeep(MB_ICONHAND);
698 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
699 DeleteNode(g_pChildWnd->hTreeWnd, 0);
701 HeapFree(GetProcessHeap(), 0, keyPath);
702 } else if (hWndDelete == g_pChildWnd->hListWnd) {
703 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
704 curIndex = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
705 while(curIndex != -1) {
706 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
708 curIndex = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, curIndex, MAKELPARAM(LVNI_SELECTED, 0));
709 if(curIndex != -1 && firstItem) {
710 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
711 MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
712 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
713 break;
716 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
718 HeapFree(GetProcessHeap(), 0, valueName);
719 break;
721 firstItem = FALSE;
722 HeapFree(GetProcessHeap(), 0, valueName);
724 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
725 HeapFree(GetProcessHeap(), 0, keyPath);
726 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
727 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
728 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
730 break;
732 case ID_EDIT_MODIFY:
734 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
735 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
736 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
737 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
738 HeapFree(GetProcessHeap(), 0, keyPath);
739 break;
741 case ID_EDIT_FIND:
742 case ID_EDIT_FINDNEXT:
744 HTREEITEM hItem;
745 if (LOWORD(wParam) == ID_EDIT_FIND &&
746 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
747 break;
748 if (!*searchString)
749 break;
750 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
751 if (hItem) {
752 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
753 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
754 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
755 SetCursor(hcursorOld);
756 if (hItem) {
757 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
758 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
759 UpdateWindow(g_pChildWnd->hTreeWnd);
760 if (row != -1) {
761 LVITEMW item;
763 item.state = 0;
764 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
765 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
767 item.state = LVIS_FOCUSED | LVIS_SELECTED;
768 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
769 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
770 SetFocus(g_pChildWnd->hListWnd);
771 } else {
772 SetFocus(g_pChildWnd->hTreeWnd);
774 } else {
775 error(hWnd, IDS_NOTFOUND, searchString);
778 break;
780 case ID_EDIT_COPYKEYNAME:
782 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
783 if (fullPath) {
784 CopyKeyName(hWnd, fullPath);
785 HeapFree(GetProcessHeap(), 0, fullPath);
787 break;
789 case ID_EDIT_NEW_KEY:
791 WCHAR newKeyW[MAX_NEW_KEY_LEN];
792 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
793 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
794 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
795 StartKeyRename(g_pChildWnd->hTreeWnd);
797 HeapFree(GetProcessHeap(), 0, keyPath);
799 break;
800 case ID_EDIT_NEW_STRINGVALUE:
801 valueType = REG_SZ;
802 goto create_value;
803 case ID_EDIT_NEW_EXPANDVALUE:
804 valueType = REG_EXPAND_SZ;
805 goto create_value;
806 case ID_EDIT_NEW_MULTI_STRINGVALUE:
807 valueType = REG_MULTI_SZ;
808 goto create_value;
809 case ID_EDIT_NEW_BINARYVALUE:
810 valueType = REG_BINARY;
811 goto create_value;
812 case ID_EDIT_NEW_DWORDVALUE:
813 valueType = REG_DWORD;
814 /* fall through */
815 create_value:
817 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
818 WCHAR newKey[MAX_NEW_KEY_LEN];
819 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
820 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
821 StartValueRename(g_pChildWnd->hListWnd);
823 HeapFree(GetProcessHeap(), 0, keyPath);
825 break;
826 case ID_EDIT_RENAME:
828 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
829 if (keyPath == 0 || *keyPath == 0) {
830 MessageBeep(MB_ICONHAND);
831 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
832 StartKeyRename(g_pChildWnd->hTreeWnd);
833 } else if (GetFocus() == g_pChildWnd->hListWnd) {
834 StartValueRename(g_pChildWnd->hListWnd);
836 HeapFree(GetProcessHeap(), 0, keyPath);
838 break;
839 case ID_REGISTRY_PRINTERSETUP:
840 /*PRINTDLG pd;*/
841 /*PrintDlg(&pd);*/
842 /*PAGESETUPDLG psd;*/
843 /*PageSetupDlg(&psd);*/
844 break;
845 case ID_REGISTRY_OPENLOCAL:
846 break;
847 case ID_REGISTRY_EXIT:
848 DestroyWindow(hWnd);
849 break;
850 case ID_FAVORITES_ADDTOFAVORITES:
852 HKEY hKey;
853 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
854 if (lpKeyPath) {
855 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
856 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
857 0, NULL, 0,
858 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
859 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
860 RegCloseKey(hKey);
863 HeapFree(GetProcessHeap(), 0, lpKeyPath);
865 break;
867 case ID_FAVORITES_REMOVEFAVORITE:
869 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
870 HKEY hKey;
871 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
872 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
873 RegDeleteValueW(hKey, favoriteName);
874 RegCloseKey(hKey);
877 break;
879 case ID_VIEW_REFRESH:
881 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
882 RefreshTreeView(g_pChildWnd->hTreeWnd);
883 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
884 HeapFree(GetProcessHeap(), 0, keyPath);
886 break;
887 /*case ID_OPTIONS_TOOLBAR:*/
888 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
889 /* break;*/
890 case ID_VIEW_STATUSBAR:
891 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
892 break;
893 case ID_HELP_HELPTOPICS:
895 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
896 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
897 break;
899 case ID_HELP_ABOUT:
900 ShowAboutBox(hWnd);
901 break;
902 case ID_VIEW_SPLIT: {
903 RECT rt;
904 POINT pt, pts;
905 GetClientRect(g_pChildWnd->hWnd, &rt);
906 pt.x = rt.left + g_pChildWnd->nSplitPos;
907 pt.y = (rt.bottom / 2);
908 pts = pt;
909 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
910 SetCursorPos(pts.x, pts.y);
911 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
912 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
914 return TRUE;
916 default:
917 return FALSE;
920 return TRUE;
923 /********************************************************************************
925 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
927 * PURPOSE: Processes messages for the main frame window.
929 * WM_COMMAND - process the application menu
930 * WM_DESTROY - post a quit message and return
934 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
936 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
938 switch (message) {
939 case WM_CREATE:
940 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
941 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
942 hWnd, NULL, hInst, 0);
943 break;
944 case WM_COMMAND:
945 if (!_CmdWndProc(hWnd, message, wParam, lParam))
946 return DefWindowProcW(hWnd, message, wParam, lParam);
947 break;
948 case WM_ACTIVATE:
949 if (LOWORD(hWnd))
950 SetFocus(g_pChildWnd->hWnd);
951 break;
952 case WM_SIZE:
953 resize_frame_client(hWnd);
954 break;
955 case WM_TIMER:
956 break;
957 case WM_ENTERMENULOOP:
958 OnEnterMenuLoop(hWnd);
959 break;
960 case WM_EXITMENULOOP:
961 OnExitMenuLoop(hWnd);
962 break;
963 case WM_INITMENUPOPUP:
964 if (!HIWORD(lParam))
965 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
966 break;
967 case WM_MENUSELECT:
968 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
969 break;
970 case WM_DESTROY:
972 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
973 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
974 PostQuitMessage(0);
976 default:
977 return DefWindowProcW(hWnd, message, wParam, lParam);
979 return 0;