regedit: Import files using 'rb' mode.
[wine.git] / programs / regedit / framewnd.c
blobed3ea9f42c27b294b42bcabb9c1c168966bb9662
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];
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:
733 case ID_EDIT_MODIFY_BIN:
735 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
736 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
737 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
738 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
739 HeapFree(GetProcessHeap(), 0, keyPath);
740 break;
742 case ID_EDIT_FIND:
743 case ID_EDIT_FINDNEXT:
745 HTREEITEM hItem;
746 if (LOWORD(wParam) == ID_EDIT_FIND &&
747 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
748 break;
749 if (!*searchString)
750 break;
751 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
752 if (hItem) {
753 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
754 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
755 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
756 SetCursor(hcursorOld);
757 if (hItem) {
758 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
759 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
760 UpdateWindow(g_pChildWnd->hTreeWnd);
761 if (row != -1) {
762 LVITEMW item;
764 item.state = 0;
765 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
766 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
768 item.state = LVIS_FOCUSED | LVIS_SELECTED;
769 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
770 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
771 SetFocus(g_pChildWnd->hListWnd);
772 } else {
773 SetFocus(g_pChildWnd->hTreeWnd);
775 } else {
776 error(hWnd, IDS_NOTFOUND, searchString);
779 break;
781 case ID_EDIT_COPYKEYNAME:
783 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
784 if (fullPath) {
785 CopyKeyName(hWnd, fullPath);
786 HeapFree(GetProcessHeap(), 0, fullPath);
788 break;
790 case ID_EDIT_NEW_KEY:
792 WCHAR newKeyW[MAX_NEW_KEY_LEN];
793 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
794 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
795 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
796 StartKeyRename(g_pChildWnd->hTreeWnd);
798 HeapFree(GetProcessHeap(), 0, keyPath);
800 break;
801 case ID_EDIT_NEW_STRINGVALUE:
802 valueType = REG_SZ;
803 goto create_value;
804 case ID_EDIT_NEW_EXPANDVALUE:
805 valueType = REG_EXPAND_SZ;
806 goto create_value;
807 case ID_EDIT_NEW_MULTI_STRINGVALUE:
808 valueType = REG_MULTI_SZ;
809 goto create_value;
810 case ID_EDIT_NEW_BINARYVALUE:
811 valueType = REG_BINARY;
812 goto create_value;
813 case ID_EDIT_NEW_DWORDVALUE:
814 valueType = REG_DWORD;
815 /* fall through */
816 create_value:
818 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
819 WCHAR newKey[MAX_NEW_KEY_LEN];
820 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
821 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
822 StartValueRename(g_pChildWnd->hListWnd);
824 HeapFree(GetProcessHeap(), 0, keyPath);
826 break;
827 case ID_EDIT_RENAME:
829 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
830 if (keyPath == 0 || *keyPath == 0) {
831 MessageBeep(MB_ICONHAND);
832 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
833 StartKeyRename(g_pChildWnd->hTreeWnd);
834 } else if (GetFocus() == g_pChildWnd->hListWnd) {
835 StartValueRename(g_pChildWnd->hListWnd);
837 HeapFree(GetProcessHeap(), 0, keyPath);
839 break;
840 case ID_REGISTRY_PRINTERSETUP:
841 /*PRINTDLG pd;*/
842 /*PrintDlg(&pd);*/
843 /*PAGESETUPDLG psd;*/
844 /*PageSetupDlg(&psd);*/
845 break;
846 case ID_REGISTRY_OPENLOCAL:
847 break;
848 case ID_REGISTRY_EXIT:
849 DestroyWindow(hWnd);
850 break;
851 case ID_FAVORITES_ADDTOFAVORITES:
853 HKEY hKey;
854 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
855 if (lpKeyPath) {
856 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
857 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
858 0, NULL, 0,
859 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
860 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
861 RegCloseKey(hKey);
864 HeapFree(GetProcessHeap(), 0, lpKeyPath);
866 break;
868 case ID_FAVORITES_REMOVEFAVORITE:
870 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
871 HKEY hKey;
872 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
873 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
874 RegDeleteValueW(hKey, favoriteName);
875 RegCloseKey(hKey);
878 break;
880 case ID_VIEW_REFRESH:
882 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
883 RefreshTreeView(g_pChildWnd->hTreeWnd);
884 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
885 HeapFree(GetProcessHeap(), 0, keyPath);
887 break;
888 /*case ID_OPTIONS_TOOLBAR:*/
889 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
890 /* break;*/
891 case ID_VIEW_STATUSBAR:
892 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
893 break;
894 case ID_HELP_HELPTOPICS:
896 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
897 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
898 break;
900 case ID_HELP_ABOUT:
901 ShowAboutBox(hWnd);
902 break;
903 case ID_VIEW_SPLIT: {
904 RECT rt;
905 POINT pt, pts;
906 GetClientRect(g_pChildWnd->hWnd, &rt);
907 pt.x = rt.left + g_pChildWnd->nSplitPos;
908 pt.y = (rt.bottom / 2);
909 pts = pt;
910 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
911 SetCursorPos(pts.x, pts.y);
912 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
913 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
915 return TRUE;
917 default:
918 return FALSE;
921 return TRUE;
924 /********************************************************************************
926 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
928 * PURPOSE: Processes messages for the main frame window.
930 * WM_COMMAND - process the application menu
931 * WM_DESTROY - post a quit message and return
935 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
937 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
939 switch (message) {
940 case WM_CREATE:
941 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
942 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
943 hWnd, NULL, hInst, 0);
944 break;
945 case WM_COMMAND:
946 if (!_CmdWndProc(hWnd, message, wParam, lParam))
947 return DefWindowProcW(hWnd, message, wParam, lParam);
948 break;
949 case WM_ACTIVATE:
950 if (LOWORD(hWnd))
951 SetFocus(g_pChildWnd->hWnd);
952 break;
953 case WM_SIZE:
954 resize_frame_client(hWnd);
955 break;
956 case WM_TIMER:
957 break;
958 case WM_ENTERMENULOOP:
959 OnEnterMenuLoop(hWnd);
960 break;
961 case WM_EXITMENULOOP:
962 OnExitMenuLoop(hWnd);
963 break;
964 case WM_INITMENUPOPUP:
965 if (!HIWORD(lParam))
966 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
967 break;
968 case WM_MENUSELECT:
969 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
970 break;
971 case WM_DESTROY:
973 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
974 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
975 PostQuitMessage(0);
977 default:
978 return DefWindowProcW(hWnd, message, wParam, lParam);
980 return 0;