regsvr32: Use neutral language for the version resource.
[wine.git] / programs / regedit / framewnd.c
blob1c4885aeba8e7d7ab2b0bdaf764aea8987bc0d14
1 /*
2 * Regedit frame window
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
23 #include <windows.h>
24 #include <commctrl.h>
25 #include <commdlg.h>
26 #include <cderr.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <shellapi.h>
31 #include "main.h"
32 #include "regproc.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
38 /********************************************************************************
39 * Global and Local Variables:
42 static const WCHAR favoritesKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p','l','e','t','s','\\','R','e','g','E','d','i','t','\\','F','a','v','o','r','i','t','e','s',0};
43 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
44 static WCHAR favoriteName[128];
45 static WCHAR searchString[128];
46 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
48 static WCHAR FileNameBuffer[_MAX_PATH];
49 static WCHAR FileTitleBuffer[_MAX_PATH];
50 static WCHAR FilterBuffer[_MAX_PATH];
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 && 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 rb_mode[] = {'r','b',0};
339 BOOL Success;
340 FILE* reg_file = _wfopen(filename, rb_mode);
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];
357 HKEY root_key = NULL;
358 WCHAR *key_path;
360 InitOpenFileName(hWnd, &ofn);
361 ofn.Flags |= OFN_ENABLESIZING;
362 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
363 ofn.lpstrTitle = title;
364 if (GetOpenFileNameW(&ofn)) {
365 if (!import_registry_filename(ofn.lpstrFile)) {
366 messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
367 return FALSE;
368 } else {
369 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
370 IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
372 } else {
373 CheckCommDlgError(hWnd);
375 RefreshTreeView(g_pChildWnd->hTreeWnd);
377 key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
378 RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
379 HeapFree(GetProcessHeap(), 0, key_path);
381 return TRUE;
385 static BOOL ExportRegistryFile(HWND hWnd)
387 OPENFILENAMEW ofn;
388 WCHAR title[128];
390 InitOpenFileName(hWnd, &ofn);
391 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
392 ofn.lpstrTitle = title;
393 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
394 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
395 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
396 if (GetSaveFileNameW(&ofn)) {
397 BOOL result;
398 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
399 if (!result) {
400 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
401 return FALSE;
403 } else {
404 CheckCommDlgError(hWnd);
406 return TRUE;
409 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
411 #if 1
412 PRINTDLGW pd;
414 ZeroMemory(&pd, sizeof(PRINTDLGW));
415 pd.lStructSize = sizeof(PRINTDLGW);
416 pd.hwndOwner = hWnd;
417 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
418 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
419 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
420 pd.nCopies = 1;
421 pd.nFromPage = 0xFFFF;
422 pd.nToPage = 0xFFFF;
423 pd.nMinPage = 1;
424 pd.nMaxPage = 0xFFFF;
425 if (PrintDlgW(&pd)) {
426 FIXME("printing is not yet implemented.\n");
427 /* GDI calls to render output. */
428 DeleteDC(pd.hDC); /* Delete DC when done.*/
430 #else
431 HRESULT hResult;
432 PRINTDLGEXW pd;
434 hResult = PrintDlgExW(&pd);
435 if (hResult == S_OK) {
436 switch (pd.dwResultAction) {
437 case PD_RESULT_APPLY:
438 /*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. */
439 FIXME("printing is not yet implemented.\n");
440 break;
441 case PD_RESULT_CANCEL:
442 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
443 break;
444 case PD_RESULT_PRINT:
445 FIXME("printing is not yet implemented.\n");
446 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
447 break;
448 default:
449 break;
451 } else {
452 switch (hResult) {
453 case E_OUTOFMEMORY:
454 /*Insufficient memory. */
455 break;
456 case E_INVALIDARG:
457 /* One or more arguments are invalid. */
458 break;
459 case E_POINTER:
460 /*Invalid pointer. */
461 break;
462 case E_HANDLE:
463 /*Invalid handle. */
464 break;
465 case E_FAIL:
466 /*Unspecified error. */
467 break;
468 default:
469 break;
471 return FALSE;
473 #endif
474 return TRUE;
477 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
479 BOOL result;
481 result = OpenClipboard(hWnd);
482 if (result) {
483 result = EmptyClipboard();
484 if (result) {
485 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
486 HANDLE hClipData = GlobalAlloc(GHND, len);
487 LPVOID pLoc = GlobalLock(hClipData);
488 lstrcpyW(pLoc, keyName);
489 GlobalUnlock(hClipData);
490 SetClipboardData(CF_UNICODETEXT, hClipData);
492 } else {
493 /* error emptying clipboard*/
494 /* DWORD dwError = GetLastError(); */
497 if (!CloseClipboard()) {
498 /* error closing clipboard*/
499 /* DWORD dwError = GetLastError(); */
502 } else {
503 /* error opening clipboard*/
504 /* DWORD dwError = GetLastError(); */
507 return result;
510 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
512 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
514 switch(uMsg) {
515 case WM_INITDIALOG:
516 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
517 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
518 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
519 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
520 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
521 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
522 SetWindowTextW(hwndValue, searchString);
523 return TRUE;
524 case WM_COMMAND:
525 switch(LOWORD(wParam)) {
526 case IDC_VALUE_NAME:
527 if (HIWORD(wParam) == EN_UPDATE) {
528 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
529 return TRUE;
531 break;
532 case IDOK:
533 if (GetWindowTextLengthW(hwndValue)>0) {
534 int mask = 0;
535 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
536 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
537 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
538 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
539 searchMask = mask;
540 GetWindowTextW(hwndValue, searchString, 128);
541 EndDialog(hwndDlg, IDOK);
543 return TRUE;
544 case IDCANCEL:
545 EndDialog(hwndDlg, IDCANCEL);
546 return TRUE;
548 break;
550 return FALSE;
553 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
555 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
557 switch(uMsg) {
558 case WM_INITDIALOG:
560 HKEY hKeyRoot = NULL;
561 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
563 if(!ItemPath || !*ItemPath)
564 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
565 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
566 SetWindowTextW(hwndValue, ItemPath);
567 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
568 HeapFree(GetProcessHeap(), 0, ItemPath);
569 return TRUE;
571 case WM_COMMAND:
572 switch(LOWORD(wParam)) {
573 case IDC_VALUE_NAME:
574 if (HIWORD(wParam) == EN_UPDATE) {
575 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
576 return TRUE;
578 break;
579 case IDOK:
580 if (GetWindowTextLengthW(hwndValue)>0) {
581 GetWindowTextW(hwndValue, favoriteName, 128);
582 EndDialog(hwndDlg, IDOK);
584 return TRUE;
585 case IDCANCEL:
586 EndDialog(hwndDlg, IDCANCEL);
587 return TRUE;
589 break;
591 return FALSE;
594 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
596 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
598 switch(uMsg) {
599 case WM_INITDIALOG: {
600 HKEY hKey;
601 int i = 0;
602 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
603 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
604 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
605 WCHAR namebuf[KEY_MAX_LEN];
606 BYTE valuebuf[4096];
607 DWORD ksize, vsize, type;
608 LONG error;
609 do {
610 ksize = KEY_MAX_LEN;
611 vsize = sizeof(valuebuf);
612 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
613 if (error != ERROR_SUCCESS)
614 break;
615 if (type == REG_SZ) {
616 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
618 i++;
619 } while(error == ERROR_SUCCESS);
620 RegCloseKey(hKey);
622 else
623 return FALSE;
624 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
625 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
626 return TRUE;
628 case WM_COMMAND:
629 switch(LOWORD(wParam)) {
630 case IDC_NAME_LIST:
631 if (HIWORD(wParam) == LBN_SELCHANGE) {
632 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
633 return TRUE;
635 break;
636 case IDOK: {
637 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
638 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
639 if (len>0) {
640 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
641 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
642 if (len>127)
643 lpName[127] = '\0';
644 lstrcpyW(favoriteName, lpName);
645 EndDialog(hwndDlg, IDOK);
646 HeapFree(GetProcessHeap(), 0, lpName);
648 return TRUE;
650 case IDCANCEL:
651 EndDialog(hwndDlg, IDCANCEL);
652 return TRUE;
654 break;
656 return FALSE;
659 /*******************************************************************************
661 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
663 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
666 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
668 HKEY hKeyRoot = 0;
669 DWORD valueType;
670 int curIndex;
671 BOOL firstItem = TRUE;
673 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
674 HKEY hKey;
675 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
676 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
677 WCHAR namebuf[KEY_MAX_LEN];
678 BYTE valuebuf[4096];
679 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
680 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
681 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
682 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
683 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
685 RegCloseKey(hKey);
687 return TRUE;
689 switch (LOWORD(wParam)) {
690 case ID_REGISTRY_IMPORTREGISTRYFILE:
691 ImportRegistryFile(hWnd);
692 break;
693 case ID_EDIT_EXPORT:
694 case ID_REGISTRY_EXPORTREGISTRYFILE:
695 ExportRegistryFile(hWnd);
696 break;
697 case ID_REGISTRY_PRINT:
699 const WCHAR empty = 0;
700 PrintRegistryHive(hWnd, &empty);
701 break;
703 case ID_EDIT_DELETE:
705 HWND hWndDelete = GetFocus();
706 if (hWndDelete == g_pChildWnd->hTreeWnd) {
707 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
708 if (keyPath == 0 || *keyPath == 0) {
709 MessageBeep(MB_ICONHAND);
710 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
711 DeleteNode(g_pChildWnd->hTreeWnd, 0);
713 HeapFree(GetProcessHeap(), 0, keyPath);
714 } else if (hWndDelete == g_pChildWnd->hListWnd) {
715 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
716 curIndex = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
717 while(curIndex != -1) {
718 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
720 curIndex = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, curIndex, MAKELPARAM(LVNI_SELECTED, 0));
721 if(curIndex != -1 && firstItem) {
722 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_VALUE_TEXT_MULTIPLE),
723 MAKEINTRESOURCEW(IDS_DELETE_VALUE_TITLE),
724 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
725 break;
728 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
730 HeapFree(GetProcessHeap(), 0, valueName);
731 break;
733 firstItem = FALSE;
734 HeapFree(GetProcessHeap(), 0, valueName);
736 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
737 HeapFree(GetProcessHeap(), 0, keyPath);
738 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
739 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
740 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
742 break;
744 case ID_EDIT_MODIFY:
745 case ID_EDIT_MODIFY_BIN:
747 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
748 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
749 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
750 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
751 HeapFree(GetProcessHeap(), 0, keyPath);
752 break;
754 case ID_EDIT_FIND:
755 case ID_EDIT_FINDNEXT:
757 HTREEITEM hItem;
758 if (LOWORD(wParam) == ID_EDIT_FIND &&
759 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
760 break;
761 if (!*searchString)
762 break;
763 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
764 if (hItem) {
765 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
766 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
767 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
768 SetCursor(hcursorOld);
769 if (hItem) {
770 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
771 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
772 UpdateWindow(g_pChildWnd->hTreeWnd);
773 if (row != -1) {
774 LVITEMW item;
776 item.state = 0;
777 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
778 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
780 item.state = LVIS_FOCUSED | LVIS_SELECTED;
781 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
782 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
783 SetFocus(g_pChildWnd->hListWnd);
784 } else {
785 SetFocus(g_pChildWnd->hTreeWnd);
787 } else {
788 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
791 break;
793 case ID_EDIT_COPYKEYNAME:
795 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
796 if (fullPath) {
797 CopyKeyName(hWnd, fullPath);
798 HeapFree(GetProcessHeap(), 0, fullPath);
800 break;
802 case ID_EDIT_NEW_KEY:
804 WCHAR newKeyW[MAX_NEW_KEY_LEN];
805 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
806 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
807 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
808 StartKeyRename(g_pChildWnd->hTreeWnd);
810 HeapFree(GetProcessHeap(), 0, keyPath);
812 break;
813 case ID_EDIT_NEW_STRINGVALUE:
814 valueType = REG_SZ;
815 goto create_value;
816 case ID_EDIT_NEW_EXPANDVALUE:
817 valueType = REG_EXPAND_SZ;
818 goto create_value;
819 case ID_EDIT_NEW_MULTI_STRINGVALUE:
820 valueType = REG_MULTI_SZ;
821 goto create_value;
822 case ID_EDIT_NEW_BINARYVALUE:
823 valueType = REG_BINARY;
824 goto create_value;
825 case ID_EDIT_NEW_DWORDVALUE:
826 valueType = REG_DWORD;
827 /* fall through */
828 create_value:
830 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
831 WCHAR newKey[MAX_NEW_KEY_LEN];
832 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
833 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
834 StartValueRename(g_pChildWnd->hListWnd);
836 HeapFree(GetProcessHeap(), 0, keyPath);
838 break;
839 case ID_EDIT_RENAME:
841 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
842 if (keyPath == 0 || *keyPath == 0) {
843 MessageBeep(MB_ICONHAND);
844 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
845 StartKeyRename(g_pChildWnd->hTreeWnd);
846 } else if (GetFocus() == g_pChildWnd->hListWnd) {
847 StartValueRename(g_pChildWnd->hListWnd);
849 HeapFree(GetProcessHeap(), 0, keyPath);
851 break;
852 case ID_REGISTRY_PRINTERSETUP:
853 /*PRINTDLG pd;*/
854 /*PrintDlg(&pd);*/
855 /*PAGESETUPDLG psd;*/
856 /*PageSetupDlg(&psd);*/
857 break;
858 case ID_REGISTRY_OPENLOCAL:
859 break;
860 case ID_REGISTRY_EXIT:
861 DestroyWindow(hWnd);
862 break;
863 case ID_FAVORITES_ADDTOFAVORITES:
865 HKEY hKey;
866 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
867 if (lpKeyPath) {
868 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
869 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
870 0, NULL, 0,
871 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
872 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
873 RegCloseKey(hKey);
876 HeapFree(GetProcessHeap(), 0, lpKeyPath);
878 break;
880 case ID_FAVORITES_REMOVEFAVORITE:
882 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
883 HKEY hKey;
884 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
885 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
886 RegDeleteValueW(hKey, favoriteName);
887 RegCloseKey(hKey);
890 break;
892 case ID_VIEW_REFRESH:
894 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
895 RefreshTreeView(g_pChildWnd->hTreeWnd);
896 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
897 HeapFree(GetProcessHeap(), 0, keyPath);
899 break;
900 /*case ID_OPTIONS_TOOLBAR:*/
901 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
902 /* break;*/
903 case ID_VIEW_STATUSBAR:
904 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
905 break;
906 case ID_HELP_HELPTOPICS:
908 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
909 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
910 break;
912 case ID_HELP_ABOUT:
913 ShowAboutBox(hWnd);
914 break;
915 case ID_VIEW_SPLIT: {
916 RECT rt;
917 POINT pt, pts;
918 GetClientRect(g_pChildWnd->hWnd, &rt);
919 pt.x = rt.left + g_pChildWnd->nSplitPos;
920 pt.y = (rt.bottom / 2);
921 pts = pt;
922 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
923 SetCursorPos(pts.x, pts.y);
924 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
925 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
927 return TRUE;
929 default:
930 return FALSE;
933 return TRUE;
936 /********************************************************************************
938 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
940 * PURPOSE: Processes messages for the main frame window.
942 * WM_COMMAND - process the application menu
943 * WM_DESTROY - post a quit message and return
947 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
949 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
951 switch (message) {
952 case WM_CREATE:
953 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
954 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
955 hWnd, NULL, hInst, 0);
956 break;
957 case WM_COMMAND:
958 if (!_CmdWndProc(hWnd, message, wParam, lParam))
959 return DefWindowProcW(hWnd, message, wParam, lParam);
960 break;
961 case WM_ACTIVATE:
962 if (LOWORD(hWnd))
963 SetFocus(g_pChildWnd->hWnd);
964 break;
965 case WM_SIZE:
966 resize_frame_client(hWnd);
967 break;
968 case WM_TIMER:
969 break;
970 case WM_ENTERMENULOOP:
971 OnEnterMenuLoop(hWnd);
972 break;
973 case WM_EXITMENULOOP:
974 OnExitMenuLoop(hWnd);
975 break;
976 case WM_INITMENUPOPUP:
977 if (!HIWORD(lParam))
978 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
979 break;
980 case WM_MENUSELECT:
981 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
982 break;
983 case WM_DESTROY:
985 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
986 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
987 PostQuitMessage(0);
989 default:
990 return DefWindowProcW(hWnd, message, wParam, lParam);
992 return 0;