e3d695a67280f9e80484e59d58218b3abb4a5e37
[reactos.git] / base / applications / regedit / framewnd.c
1 /*
2 * Regedit frame window
3 *
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5 *
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.
10 *
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.
15 *
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "regedit.h"
22
23 #include <commdlg.h>
24 #include <cderr.h>
25 #include <objsel.h>
26
27 /********************************************************************************
28 * Global and Local Variables:
29 */
30
31 #define FAVORITES_MENU_POSITION 3
32
33 static WCHAR s_szFavoritesRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
34
35 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
36
37 extern WCHAR Suggestions[256];
38 /*******************************************************************************
39 * Local module support methods
40 */
41
42 static void resize_frame_rect(HWND hWnd, PRECT prect)
43 {
44 if (IsWindowVisible(hStatusBar))
45 {
46 RECT rt;
47
48 SetupStatusBar(hWnd, TRUE);
49 GetWindowRect(hStatusBar, &rt);
50 prect->bottom -= rt.bottom - rt.top;
51 }
52 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
53 }
54
55 static void resize_frame_client(HWND hWnd)
56 {
57 RECT rect;
58
59 GetClientRect(hWnd, &rect);
60 resize_frame_rect(hWnd, &rect);
61 }
62
63 /********************************************************************************/
64
65 static void OnInitMenu(HWND hWnd)
66 {
67 LONG lResult;
68 HKEY hKey = NULL;
69 DWORD dwIndex, cbValueName, cbValueData, dwType;
70 WCHAR szValueName[256];
71 BYTE abValueData[256];
72 static int s_nFavoriteMenuSubPos = -1;
73 HMENU hMenu;
74 BOOL bDisplayedAny = FALSE;
75
76 /* Find Favorites menu and clear it out */
77 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
78 if (!hMenu)
79 goto done;
80 if (s_nFavoriteMenuSubPos < 0)
81 {
82 s_nFavoriteMenuSubPos = GetMenuItemCount(hMenu);
83 }
84 else
85 {
86 while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION)) ;
87 }
88
89 lResult = RegOpenKeyW(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
90 if (lResult != ERROR_SUCCESS)
91 goto done;
92
93 dwIndex = 0;
94 do
95 {
96 cbValueName = ARRAY_SIZE(szValueName);
97 cbValueData = sizeof(abValueData);
98 lResult = RegEnumValueW(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
99 if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
100 {
101 if (!bDisplayedAny)
102 {
103 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
104 bDisplayedAny = TRUE;
105 }
106 AppendMenu(hMenu, 0, ID_FAVORITES_MIN + GetMenuItemCount(hMenu), szValueName);
107 }
108 dwIndex++;
109 }
110 while(lResult == ERROR_SUCCESS);
111
112 done:
113 if (hKey)
114 RegCloseKey(hKey);
115 }
116
117 static void OnEnterMenuLoop(HWND hWnd)
118 {
119 int nParts;
120 UNREFERENCED_PARAMETER(hWnd);
121
122 /* Update the status bar pane sizes */
123 nParts = -1;
124 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
125 bInMenuLoop = TRUE;
126 SendMessageW(hStatusBar, SB_SETTEXTW, (WPARAM)0, (LPARAM)L"");
127 }
128
129 static void OnExitMenuLoop(HWND hWnd)
130 {
131 bInMenuLoop = FALSE;
132 /* Update the status bar pane sizes*/
133 SetupStatusBar(hWnd, TRUE);
134 UpdateStatusBar();
135 }
136
137 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
138 {
139 WCHAR str[100];
140
141 wcscpy(str, L"");
142 if (nFlags & MF_POPUP)
143 {
144 if (hSysMenu != GetMenu(hWnd))
145 {
146 if (nItemID == 2) nItemID = 5;
147 }
148 }
149 if (LoadStringW(hInst, nItemID, str, 100))
150 {
151 /* load appropriate string*/
152 LPWSTR lpsz = str;
153 /* first newline terminates actual string*/
154 lpsz = wcschr(lpsz, L'\n');
155 if (lpsz != NULL)
156 *lpsz = L'\0';
157 }
158 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
159 }
160
161 void SetupStatusBar(HWND hWnd, BOOL bResize)
162 {
163 RECT rc;
164 int nParts;
165 GetClientRect(hWnd, &rc);
166 nParts = rc.right;
167 /* nParts = -1;*/
168 if (bResize)
169 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
170 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
171 }
172
173 void UpdateStatusBar(void)
174 {
175 HKEY hKeyRoot;
176 LPCWSTR pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
177
178 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)pszKeyPath);
179 }
180
181 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
182 {
183 BOOL vis = IsWindowVisible(hchild);
184 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
185
186 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
187 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
188 resize_frame_client(hWnd);
189 }
190
191 static BOOL CheckCommDlgError(HWND hWnd)
192 {
193 DWORD dwErrorCode = CommDlgExtendedError();
194 UNREFERENCED_PARAMETER(hWnd);
195 switch (dwErrorCode)
196 {
197 case CDERR_DIALOGFAILURE:
198 break;
199 case CDERR_FINDRESFAILURE:
200 break;
201 case CDERR_NOHINSTANCE:
202 break;
203 case CDERR_INITIALIZATION:
204 break;
205 case CDERR_NOHOOK:
206 break;
207 case CDERR_LOCKRESFAILURE:
208 break;
209 case CDERR_NOTEMPLATE:
210 break;
211 case CDERR_LOADRESFAILURE:
212 break;
213 case CDERR_STRUCTSIZE:
214 break;
215 case CDERR_LOADSTRFAILURE:
216 break;
217 case FNERR_BUFFERTOOSMALL:
218 break;
219 case CDERR_MEMALLOCFAILURE:
220 break;
221 case FNERR_INVALIDFILENAME:
222 break;
223 case CDERR_MEMLOCKFAILURE:
224 break;
225 case FNERR_SUBCLASSFAILURE:
226 break;
227 default:
228 break;
229 }
230 return TRUE;
231 }
232
233 WCHAR FileNameBuffer[_MAX_PATH];
234 WCHAR FileTitleBuffer[_MAX_PATH];
235
236 typedef struct
237 {
238 UINT DisplayID;
239 UINT FilterID;
240 } FILTERPAIR, *PFILTERPAIR;
241
242 void
243 BuildFilterStrings(WCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
244 {
245 int i, c;
246
247 c = 0;
248 for(i = 0; i < PairCount; i++)
249 {
250 c += LoadStringW(hInst, Pairs[i].DisplayID, &Filter[c], 255);
251 Filter[++c] = L'\0';
252 c += LoadStringW(hInst, Pairs[i].FilterID, &Filter[c], 255);
253 Filter[++c] = L'\0';
254 }
255 Filter[++c] = L'\0';
256 }
257
258 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
259 {
260 FILTERPAIR FilterPairs[4];
261 static WCHAR Filter[1024];
262
263 memset(pofn, 0, sizeof(OPENFILENAME));
264 pofn->lStructSize = sizeof(OPENFILENAME);
265 pofn->hwndOwner = hWnd;
266 pofn->hInstance = hInst;
267
268 /* create filter string */
269 FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
270 FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
271 FilterPairs[1].DisplayID = IDS_FLT_HIVFILES;
272 FilterPairs[1].FilterID = IDS_FLT_HIVFILES_FLT;
273 FilterPairs[2].DisplayID = IDS_FLT_REGEDIT4;
274 FilterPairs[2].FilterID = IDS_FLT_REGEDIT4_FLT;
275 FilterPairs[3].DisplayID = IDS_FLT_ALLFILES;
276 FilterPairs[3].FilterID = IDS_FLT_ALLFILES_FLT;
277 BuildFilterStrings(Filter, FilterPairs, ARRAY_SIZE(FilterPairs));
278
279 pofn->lpstrFilter = Filter;
280 pofn->lpstrFile = FileNameBuffer;
281 pofn->nMaxFile = _MAX_PATH;
282 pofn->lpstrFileTitle = FileTitleBuffer;
283 pofn->nMaxFileTitle = _MAX_PATH;
284 pofn->Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
285 pofn->lpstrDefExt = L"reg";
286 return TRUE;
287 }
288
289 #define LOADHIVE_KEYNAMELENGTH 128
290
291 static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
292 {
293 static LPWSTR sKey = NULL;
294 switch(uMsg)
295 {
296 case WM_INITDIALOG:
297 sKey = (LPWSTR)lParam;
298 break;
299 case WM_COMMAND:
300 switch(LOWORD(wParam))
301 {
302 case IDOK:
303 if(GetDlgItemTextW(hWndDlg, IDC_EDIT_KEY, sKey, LOADHIVE_KEYNAMELENGTH))
304 return EndDialog(hWndDlg, -1);
305 else
306 return EndDialog(hWndDlg, 0);
307 case IDCANCEL:
308 return EndDialog(hWndDlg, 0);
309 }
310 break;
311 }
312 return FALSE;
313 }
314
315 static BOOL EnablePrivilege(LPCWSTR lpszPrivilegeName, LPCWSTR lpszSystemName, BOOL bEnablePrivilege)
316 {
317 BOOL bRet = FALSE;
318 HANDLE hToken = NULL;
319
320 if (OpenProcessToken(GetCurrentProcess(),
321 TOKEN_ADJUST_PRIVILEGES,
322 &hToken))
323 {
324 TOKEN_PRIVILEGES tp;
325
326 tp.PrivilegeCount = 1;
327 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
328
329 if (LookupPrivilegeValueW(lpszSystemName,
330 lpszPrivilegeName,
331 &tp.Privileges[0].Luid))
332 {
333 bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
334
335 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
336 bRet = FALSE;
337 }
338
339 CloseHandle(hToken);
340 }
341
342 return bRet;
343 }
344
345 static BOOL LoadHive(HWND hWnd)
346 {
347 OPENFILENAME ofn;
348 WCHAR Caption[128];
349 LPCWSTR pszKeyPath;
350 WCHAR xPath[LOADHIVE_KEYNAMELENGTH];
351 HKEY hRootKey;
352 WCHAR Filter[1024];
353 FILTERPAIR filter;
354 /* get the item key to load the hive in */
355 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
356 /* initialize the "open file" dialog */
357 InitOpenFileName(hWnd, &ofn);
358 /* build the "All Files" filter up */
359 filter.DisplayID = IDS_FLT_ALLFILES;
360 filter.FilterID = IDS_FLT_ALLFILES_FLT;
361 BuildFilterStrings(Filter, &filter, 1);
362 ofn.lpstrFilter = Filter;
363 /* load and set the caption and flags for dialog */
364 LoadStringW(hInst, IDS_LOAD_HIVE, Caption, ARRAY_SIZE(Caption));
365 ofn.lpstrTitle = Caption;
366 ofn.Flags |= OFN_ENABLESIZING;
367 /* ofn.lCustData = ;*/
368 /* now load the hive */
369 if (GetOpenFileName(&ofn))
370 {
371 if (DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_LOADHIVE), hWnd,
372 &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
373 {
374 LONG regLoadResult;
375
376 /* Enable the 'restore' privilege, load the hive, disable the privilege */
377 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
378 regLoadResult = RegLoadKeyW(hRootKey, xPath, ofn.lpstrFile);
379 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
380
381 if(regLoadResult == ERROR_SUCCESS)
382 {
383 /* refresh tree and list views */
384 RefreshTreeView(g_pChildWnd->hTreeWnd);
385 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
386 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
387 }
388 else
389 {
390 ErrorMessageBox(hWnd, Caption, regLoadResult);
391 return FALSE;
392 }
393 }
394 }
395 else
396 {
397 CheckCommDlgError(hWnd);
398 }
399 return TRUE;
400 }
401
402 static BOOL UnloadHive(HWND hWnd)
403 {
404 WCHAR Caption[128];
405 LPCWSTR pszKeyPath;
406 HKEY hRootKey;
407 LONG regUnloadResult;
408
409 /* get the item key to unload */
410 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
411 /* load and set the caption and flags for dialog */
412 LoadStringW(hInst, IDS_UNLOAD_HIVE, Caption, ARRAY_SIZE(Caption));
413
414 /* Enable the 'restore' privilege, unload the hive, disable the privilege */
415 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
416 regUnloadResult = RegUnLoadKeyW(hRootKey, pszKeyPath);
417 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
418
419 if(regUnloadResult == ERROR_SUCCESS)
420 {
421 /* refresh tree and list views */
422 RefreshTreeView(g_pChildWnd->hTreeWnd);
423 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
424 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
425 }
426 else
427 {
428 ErrorMessageBox(hWnd, Caption, regUnloadResult);
429 return FALSE;
430 }
431 return TRUE;
432 }
433
434 static BOOL ImportRegistryFile(HWND hWnd)
435 {
436 BOOL bRet = FALSE;
437 OPENFILENAME ofn;
438 WCHAR Caption[128], szTitle[512], szText[512];
439 HKEY hKeyRoot;
440 LPCWSTR pszKeyPath;
441
442 /* Figure out in which key path we are importing */
443 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
444
445 InitOpenFileName(hWnd, &ofn);
446 LoadStringW(hInst, IDS_IMPORT_REG_FILE, Caption, ARRAY_SIZE(Caption));
447 ofn.lpstrTitle = Caption;
448 ofn.Flags |= OFN_ENABLESIZING;
449 /* ofn.lCustData = ;*/
450 if (GetOpenFileName(&ofn))
451 {
452 /* Look at the extension of the file to determine its type */
453 if (ofn.nFileExtension >= 1 &&
454 _wcsicmp(ofn.lpstrFile + ofn.nFileExtension, L"reg") == 0) /* REGEDIT4 or Windows Registry Editor Version 5.00 */
455 {
456 /* Open the file */
457 FILE* fp = _wfopen(ofn.lpstrFile, L"rb");
458
459 /* Import it */
460 if (fp == NULL || !import_registry_file(fp))
461 {
462 /* Error opening the file */
463 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
464 LoadStringW(hInst, IDS_IMPORT_ERROR, szText, ARRAY_SIZE(szText));
465 InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
466 bRet = FALSE;
467 }
468 else
469 {
470 /* Show successful import */
471 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
472 LoadStringW(hInst, IDS_IMPORT_OK, szText, ARRAY_SIZE(szText));
473 InfoMessageBox(hWnd, MB_OK | MB_ICONINFORMATION, szTitle, szText, ofn.lpstrFile);
474 bRet = TRUE;
475 }
476
477 /* Close the file */
478 if (fp) fclose(fp);
479 }
480 else /* Registry Hive Files */
481 {
482 LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_CAPTION, szTitle, ARRAY_SIZE(szTitle));
483 LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_MSG, szText, ARRAY_SIZE(szText));
484
485 /* Display a confirmation message */
486 if (MessageBoxW(g_pChildWnd->hWnd, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDYES)
487 {
488 LONG lResult;
489 HKEY hSubKey;
490
491 /* Open the subkey */
492 lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_WRITE, &hSubKey);
493 if (lResult == ERROR_SUCCESS)
494 {
495 /* Enable the 'restore' privilege, restore the hive then disable the privilege */
496 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
497 lResult = RegRestoreKey(hSubKey, ofn.lpstrFile, REG_FORCE_RESTORE);
498 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
499
500 /* Flush the subkey and close it */
501 RegFlushKey(hSubKey);
502 RegCloseKey(hSubKey);
503 }
504
505 /* Set the return value */
506 bRet = (lResult == ERROR_SUCCESS);
507
508 /* Display error, if any */
509 if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
510 }
511 }
512 }
513 else
514 {
515 CheckCommDlgError(hWnd);
516 }
517
518 /* refresh tree and list views */
519 RefreshTreeView(g_pChildWnd->hTreeWnd);
520 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
521 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, pszKeyPath);
522
523 return bRet;
524 }
525
526 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
527 {
528 HWND hwndExportAll;
529 HWND hwndExportBranch;
530 HWND hwndExportBranchText;
531 UINT_PTR iResult = 0;
532 OPENFILENAME *pOfn;
533 LPWSTR pszSelectedKey;
534 OFNOTIFY *pOfnNotify;
535
536 UNREFERENCED_PARAMETER(wParam);
537
538 switch(uiMsg)
539 {
540 case WM_INITDIALOG:
541 pOfn = (OPENFILENAME *) lParam;
542 pszSelectedKey = (LPWSTR) pOfn->lCustData;
543
544 hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
545 if (hwndExportAll)
546 SendMessageW(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
547
548 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
549 if (hwndExportBranch)
550 SendMessageW(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
551
552 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
553 if (hwndExportBranchText)
554 SetWindowTextW(hwndExportBranchText, pszSelectedKey);
555 break;
556
557 case WM_NOTIFY:
558 if (((NMHDR *) lParam)->code == CDN_FILEOK)
559 {
560 pOfnNotify = (OFNOTIFY *) lParam;
561 pszSelectedKey = (LPWSTR) pOfnNotify->lpOFN->lCustData;
562
563 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
564 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
565 if (hwndExportBranch && hwndExportBranchText
566 && (SendMessageW(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
567 {
568 GetWindowTextW(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
569 }
570 else
571 {
572 pszSelectedKey[0] = L'\0';
573 }
574 }
575 break;
576 }
577 return iResult;
578 }
579
580 BOOL ExportRegistryFile(HWND hWnd)
581 {
582 BOOL bRet = FALSE;
583 OPENFILENAME ofn;
584 WCHAR ExportKeyPath[_MAX_PATH] = {0};
585 WCHAR Caption[128], szTitle[512], szText[512];
586 HKEY hKeyRoot;
587 LPCWSTR pszKeyPath;
588
589 /* Figure out which key path we are exporting */
590 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
591 GetKeyName(ExportKeyPath, ARRAY_SIZE(ExportKeyPath), hKeyRoot, pszKeyPath);
592
593 InitOpenFileName(hWnd, &ofn);
594 LoadStringW(hInst, IDS_EXPORT_REG_FILE, Caption, ARRAY_SIZE(Caption));
595 ofn.lpstrTitle = Caption;
596
597 /* Only set the path if a key (not the root node) is selected */
598 if (hKeyRoot != 0)
599 {
600 ofn.lCustData = (LPARAM) ExportKeyPath;
601 }
602 ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_OVERWRITEPROMPT;
603 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
604 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORTRANGE);
605 if (GetSaveFileName(&ofn))
606 {
607 switch (ofn.nFilterIndex)
608 {
609 case 2: /* Registry Hive Files */
610 {
611 LONG lResult;
612 HKEY hSubKey;
613
614 /* Open the subkey */
615 lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_READ, &hSubKey);
616 if (lResult == ERROR_SUCCESS)
617 {
618 /* Enable the 'backup' privilege, save the hive then disable the privilege */
619 EnablePrivilege(SE_BACKUP_NAME, NULL, TRUE);
620 lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
621 if (lResult == ERROR_ALREADY_EXISTS)
622 {
623 /*
624 * We are here, that means that we already said "yes" to the confirmation dialog.
625 * So we absolutely want to replace the hive file.
626 */
627 if (DeleteFileW(ofn.lpstrFile))
628 {
629 /* Try again */
630 lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
631 }
632 }
633 EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
634
635 if (lResult != ERROR_SUCCESS)
636 {
637 /*
638 * If we are here, it's because RegSaveKeyW has failed for any reason.
639 * The problem is that even if it has failed, it has created or
640 * replaced the exported hive file with a new empty file. We don't
641 * want to keep this file, so we delete it.
642 */
643 DeleteFileW(ofn.lpstrFile);
644 }
645
646 /* Close the subkey */
647 RegCloseKey(hSubKey);
648 }
649
650 /* Set the return value */
651 bRet = (lResult == ERROR_SUCCESS);
652
653 /* Display error, if any */
654 if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
655
656 break;
657 }
658
659 case 1: /* Windows Registry Editor Version 5.00 */
660 case 3: /* REGEDIT4 */
661 default: /* All files ==> use Windows Registry Editor Version 5.00 */
662 {
663 if (!export_registry_key(ofn.lpstrFile, ExportKeyPath,
664 (ofn.nFilterIndex == 3 ? REG_FORMAT_4
665 : REG_FORMAT_5)))
666 {
667 /* Error creating the file */
668 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
669 LoadStringW(hInst, IDS_EXPORT_ERROR, szText, ARRAY_SIZE(szText));
670 InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
671 bRet = FALSE;
672 }
673 else
674 {
675 bRet = TRUE;
676 }
677
678 break;
679 }
680 }
681 }
682 else
683 {
684 CheckCommDlgError(hWnd);
685 }
686
687 return bRet;
688 }
689
690 BOOL PrintRegistryHive(HWND hWnd, LPWSTR path)
691 {
692 #if 1
693 PRINTDLG pd;
694 UNREFERENCED_PARAMETER(path);
695
696 ZeroMemory(&pd, sizeof(PRINTDLG));
697 pd.lStructSize = sizeof(PRINTDLG);
698 pd.hwndOwner = hWnd;
699 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
700 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
701 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
702 pd.nCopies = 1;
703 pd.nFromPage = 0xFFFF;
704 pd.nToPage = 0xFFFF;
705 pd.nMinPage = 1;
706 pd.nMaxPage = 0xFFFF;
707 if (PrintDlg(&pd))
708 {
709 /* GDI calls to render output. */
710 DeleteDC(pd.hDC); /* Delete DC when done.*/
711 }
712 #else
713 HRESULT hResult;
714 PRINTDLGEX pd;
715
716 hResult = PrintDlgEx(&pd);
717 if (hResult == S_OK)
718 {
719 switch (pd.dwResultAction)
720 {
721 case PD_RESULT_APPLY:
722 /*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. */
723 break;
724 case PD_RESULT_CANCEL:
725 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
726 break;
727 case PD_RESULT_PRINT:
728 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
729 break;
730 default:
731 break;
732 }
733 }
734 else
735 {
736 switch (hResult)
737 {
738 case E_OUTOFMEMORY:
739 /*Insufficient memory. */
740 break;
741 case E_INVALIDARG:
742 /* One or more arguments are invalid. */
743 break;
744 case E_POINTER:
745 /*Invalid pointer. */
746 break;
747 case E_HANDLE:
748 /*Invalid handle. */
749 break;
750 case E_FAIL:
751 /*Unspecified error. */
752 break;
753 default:
754 break;
755 }
756 return FALSE;
757 }
758 #endif
759 return TRUE;
760 }
761
762 static void ChooseFavorite(LPCWSTR pszFavorite)
763 {
764 HKEY hKey = NULL;
765 WCHAR szFavoritePath[512];
766 DWORD cbData, dwType;
767
768 if (RegOpenKeyExW(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
769 goto done;
770
771 cbData = sizeof(szFavoritePath);
772 memset(szFavoritePath, 0, sizeof(szFavoritePath));
773 if (RegQueryValueExW(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
774 goto done;
775
776 if (dwType == REG_SZ)
777 SelectNode(g_pChildWnd->hTreeWnd, szFavoritePath);
778
779 done:
780 if (hKey)
781 RegCloseKey(hKey);
782 }
783
784 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCWSTR keyName)
785 {
786 BOOL bClipboardOpened = FALSE;
787 BOOL bSuccess = FALSE;
788 WCHAR szBuffer[512];
789 HGLOBAL hGlobal;
790 LPWSTR s;
791
792 if (!OpenClipboard(hWnd))
793 goto done;
794 bClipboardOpened = TRUE;
795
796 if (!EmptyClipboard())
797 goto done;
798
799 if (!GetKeyName(szBuffer, ARRAY_SIZE(szBuffer), hRootKey, keyName))
800 goto done;
801
802 hGlobal = GlobalAlloc(GMEM_MOVEABLE, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
803 if (!hGlobal)
804 goto done;
805
806 s = GlobalLock(hGlobal);
807 wcscpy(s, szBuffer);
808 GlobalUnlock(hGlobal);
809
810 SetClipboardData(CF_UNICODETEXT, hGlobal);
811 bSuccess = TRUE;
812
813 done:
814 if (bClipboardOpened)
815 CloseClipboard();
816 return bSuccess;
817 }
818
819 static BOOL CreateNewValue(HKEY hRootKey, LPCWSTR pszKeyPath, DWORD dwType)
820 {
821 WCHAR szNewValueFormat[128];
822 WCHAR szNewValue[128];
823 int iIndex = 1;
824 BYTE data[128];
825 DWORD dwExistingType, cbData;
826 LONG lResult;
827 HKEY hKey;
828 LVFINDINFO lvfi;
829
830 if (RegOpenKeyExW(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
831 &hKey) != ERROR_SUCCESS)
832 return FALSE;
833
834 LoadStringW(hInst, IDS_NEW_VALUE, szNewValueFormat, ARRAY_SIZE(szNewValueFormat));
835
836 do
837 {
838 wsprintf(szNewValue, szNewValueFormat, iIndex++);
839 cbData = sizeof(data);
840 lResult = RegQueryValueExW(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
841 }
842 while(lResult == ERROR_SUCCESS);
843
844 switch(dwType)
845 {
846 case REG_DWORD:
847 cbData = sizeof(DWORD);
848 break;
849 case REG_SZ:
850 case REG_EXPAND_SZ:
851 cbData = sizeof(WCHAR);
852 break;
853 case REG_MULTI_SZ:
854 /*
855 * WARNING: An empty multi-string has only one null char.
856 * Indeed, multi-strings are built in the following form:
857 * str1\0str2\0...strN\0\0
858 * where each strI\0 is a null-terminated string, and it
859 * ends with a terminating empty string.
860 * Therefore an empty multi-string contains only the terminating
861 * empty string, that is, one null char.
862 */
863 cbData = sizeof(WCHAR);
864 break;
865 case REG_QWORD: /* REG_QWORD_LITTLE_ENDIAN */
866 cbData = sizeof(DWORDLONG); // == sizeof(DWORD) * 2;
867 break;
868 default:
869 cbData = 0;
870 break;
871 }
872 memset(data, 0, cbData);
873 lResult = RegSetValueExW(hKey, szNewValue, 0, dwType, data, cbData);
874 RegCloseKey(hKey);
875 if (lResult != ERROR_SUCCESS)
876 {
877 return FALSE;
878 }
879
880 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
881
882 /* locate the newly added value, and get ready to rename it */
883 memset(&lvfi, 0, sizeof(lvfi));
884 lvfi.flags = LVFI_STRING;
885 lvfi.psz = szNewValue;
886 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
887 if (iIndex >= 0)
888 (void)ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
889
890 return TRUE;
891 }
892
893 static HRESULT
894 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
895 {
896 HRESULT hRet;
897
898 *pDsObjectPicker = NULL;
899
900 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
901 NULL,
902 CLSCTX_INPROC_SERVER,
903 &IID_IDsObjectPicker,
904 (LPVOID*)pDsObjectPicker);
905 if (SUCCEEDED(hRet))
906 {
907 DSOP_INIT_INFO InitInfo;
908 static DSOP_SCOPE_INIT_INFO Scopes[] =
909 {
910 {
911 sizeof(DSOP_SCOPE_INIT_INFO),
912 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
913 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
914 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
915 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
916 0,
917 {
918 {
919 DSOP_FILTER_COMPUTERS,
920 0,
921 0
922 },
923 DSOP_DOWNLEVEL_FILTER_COMPUTERS
924 },
925 NULL,
926 NULL,
927 S_OK
928 },
929 };
930
931 InitInfo.cbSize = sizeof(InitInfo);
932 InitInfo.pwzTargetComputer = NULL;
933 InitInfo.cDsScopeInfos = ARRAY_SIZE(Scopes);
934 InitInfo.aDsScopeInfos = Scopes;
935 InitInfo.flOptions = 0;
936 InitInfo.cAttributesToFetch = 0;
937 InitInfo.apwzAttributeNames = NULL;
938
939 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
940 &InitInfo);
941
942 if (FAILED(hRet))
943 {
944 /* delete the object picker in case initialization failed! */
945 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
946 }
947 }
948
949 return hRet;
950 }
951
952 static HRESULT
953 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
954 IN HWND hwndParent OPTIONAL,
955 OUT LPWSTR lpBuffer,
956 IN UINT uSize)
957 {
958 IDataObject *pdo = NULL;
959 HRESULT hRet;
960
961 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
962 hwndParent,
963 &pdo);
964 if (hRet == S_OK)
965 {
966 STGMEDIUM stm;
967 FORMATETC fe;
968
969 fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormatW(CFSTR_DSOP_DS_SELECTION_LIST);
970 fe.ptd = NULL;
971 fe.dwAspect = DVASPECT_CONTENT;
972 fe.lindex = -1;
973 fe.tymed = TYMED_HGLOBAL;
974
975 hRet = pdo->lpVtbl->GetData(pdo,
976 &fe,
977 &stm);
978 if (SUCCEEDED(hRet))
979 {
980 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
981 if (SelectionList != NULL)
982 {
983 if (SelectionList->cItems == 1)
984 {
985 size_t nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
986 if (nlen >= uSize)
987 {
988 nlen = uSize - 1;
989 }
990
991 memcpy(lpBuffer,
992 SelectionList->aDsSelection[0].pwzName,
993 nlen * sizeof(WCHAR));
994
995 lpBuffer[nlen] = L'\0';
996 }
997
998 GlobalUnlock(stm.hGlobal);
999 }
1000
1001 ReleaseStgMedium(&stm);
1002 }
1003
1004 pdo->lpVtbl->Release(pdo);
1005 }
1006
1007 return hRet;
1008 }
1009
1010 static VOID
1011 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
1012 {
1013 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
1014 }
1015
1016 /*******************************************************************************
1017 *
1018 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
1019 *
1020 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
1021 *
1022 */
1023 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1024 {
1025 HKEY hKeyRoot = 0, hKey = 0;
1026 LPCWSTR keyPath;
1027 LPCWSTR valueName;
1028 BOOL result = TRUE;
1029 REGSAM regsam = KEY_READ;
1030 int item;
1031
1032 UNREFERENCED_PARAMETER(lParam);
1033 UNREFERENCED_PARAMETER(message);
1034
1035 switch (LOWORD(wParam))
1036 {
1037 case ID_REGISTRY_LOADHIVE:
1038 LoadHive(hWnd);
1039 return TRUE;
1040 case ID_REGISTRY_UNLOADHIVE:
1041 UnloadHive(hWnd);
1042 return TRUE;
1043 case ID_REGISTRY_IMPORTREGISTRYFILE:
1044 ImportRegistryFile(hWnd);
1045 return TRUE;
1046 case ID_REGISTRY_EXPORTREGISTRYFILE:
1047 ExportRegistryFile(hWnd);
1048 return TRUE;
1049 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
1050 {
1051 IDsObjectPicker *ObjectPicker;
1052 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1053 HRESULT hRet;
1054
1055 hRet = CoInitialize(NULL);
1056 if (SUCCEEDED(hRet))
1057 {
1058 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
1059 if (SUCCEEDED(hRet))
1060 {
1061 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
1062 hWnd,
1063 szComputerName,
1064 ARRAY_SIZE(szComputerName));
1065 if (hRet == S_OK)
1066 {
1067 /* FIXME - connect to the registry */
1068 }
1069
1070 FreeObjectPicker(ObjectPicker);
1071 }
1072
1073 CoUninitialize();
1074 }
1075
1076 return TRUE;
1077 }
1078 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
1079 return TRUE;
1080 case ID_REGISTRY_PRINT:
1081 PrintRegistryHive(hWnd, L"");
1082 return TRUE;
1083 case ID_REGISTRY_EXIT:
1084 DestroyWindow(hWnd);
1085 return TRUE;
1086 case ID_VIEW_STATUSBAR:
1087 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1088 return TRUE;
1089 case ID_HELP_HELPTOPICS:
1090 WinHelpW(hWnd, L"regedit", HELP_FINDER, 0);
1091 return TRUE;
1092 case ID_HELP_ABOUT:
1093 ShowAboutBox(hWnd);
1094 return TRUE;
1095 case ID_VIEW_SPLIT:
1096 {
1097 RECT rt;
1098 POINT pt, pts;
1099 GetClientRect(g_pChildWnd->hWnd, &rt);
1100 pt.x = rt.left + g_pChildWnd->nSplitPos;
1101 pt.y = (rt.bottom / 2);
1102 pts = pt;
1103 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
1104 {
1105 SetCursorPos(pts.x, pts.y);
1106 SetCursor(LoadCursorW(0, IDC_SIZEWE));
1107 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1108 }
1109 return TRUE;
1110 }
1111 case ID_EDIT_RENAME:
1112 case ID_EDIT_MODIFY:
1113 case ID_EDIT_MODIFY_BIN:
1114 case ID_EDIT_DELETE:
1115 regsam |= KEY_WRITE;
1116 break;
1117 }
1118
1119 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1120 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
1121 if (keyPath)
1122 {
1123 if (RegOpenKeyExW(hKeyRoot, keyPath, 0, regsam, &hKey) != ERROR_SUCCESS)
1124 hKey = 0;
1125 }
1126
1127 switch (LOWORD(wParam))
1128 {
1129 case ID_EDIT_MODIFY:
1130 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
1131 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1132 break;
1133 case ID_EDIT_MODIFY_BIN:
1134 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
1135 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1136 break;
1137 case ID_EDIT_RENAME:
1138 if (GetFocus() == g_pChildWnd->hListWnd)
1139 {
1140 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
1141 {
1142 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
1143 if(item > -1)
1144 {
1145 (void)ListView_EditLabel(g_pChildWnd->hListWnd, item);
1146 }
1147 }
1148 }
1149 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1150 {
1151 /* Get focused entry of treeview (if any) */
1152 HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
1153 if (hItem != NULL)
1154 (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, hItem);
1155 }
1156 break;
1157 case ID_EDIT_DELETE:
1158 {
1159 if (GetFocus() == g_pChildWnd->hListWnd && hKey)
1160 {
1161 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
1162 if(nSelected >= 1)
1163 {
1164 WCHAR msg[128], caption[128];
1165 LoadStringW(hInst, IDS_QUERY_DELETE_CONFIRM, caption, ARRAY_SIZE(caption));
1166 LoadStringW(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, ARRAY_SIZE(msg));
1167 if(MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
1168 {
1169 int ni, errs;
1170
1171 item = -1;
1172 errs = 0;
1173 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
1174 {
1175 valueName = GetValueName(g_pChildWnd->hListWnd, item);
1176 if(RegDeleteValueW(hKey, valueName) != ERROR_SUCCESS)
1177 {
1178 errs++;
1179 }
1180 item = ni;
1181 }
1182
1183 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1184 if(errs > 0)
1185 {
1186 LoadStringW(hInst, IDS_ERR_DELVAL_CAPTION, caption, ARRAY_SIZE(caption));
1187 LoadStringW(hInst, IDS_ERR_DELETEVALUE, msg, ARRAY_SIZE(msg));
1188 MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
1189 }
1190 }
1191 }
1192 }
1193 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1194 {
1195 if (keyPath == NULL || *keyPath == UNICODE_NULL)
1196 {
1197 MessageBeep(MB_ICONHAND);
1198 }
1199 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1200 {
1201 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1202 RefreshTreeView(g_pChildWnd->hTreeWnd);
1203 }
1204 }
1205 break;
1206 }
1207 case ID_EDIT_NEW_STRINGVALUE:
1208 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
1209 break;
1210 case ID_EDIT_NEW_BINARYVALUE:
1211 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
1212 break;
1213 case ID_EDIT_NEW_DWORDVALUE:
1214 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
1215 break;
1216 case ID_EDIT_NEW_MULTISTRINGVALUE:
1217 CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
1218 break;
1219 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
1220 CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
1221 break;
1222 case ID_EDIT_FIND:
1223 FindDialog(hWnd);
1224 break;
1225 case ID_EDIT_FINDNEXT:
1226 FindNextMessageBox(hWnd);
1227 break;
1228 case ID_EDIT_COPYKEYNAME:
1229 CopyKeyName(hWnd, hKeyRoot, keyPath);
1230 break;
1231 case ID_EDIT_PERMISSIONS:
1232 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1233 break;
1234 case ID_REGISTRY_PRINTERSETUP:
1235 /*PRINTDLG pd;*/
1236 /*PrintDlg(&pd);*/
1237 /*PAGESETUPDLG psd;*/
1238 /*PageSetupDlg(&psd);*/
1239 break;
1240 case ID_REGISTRY_OPENLOCAL:
1241 break;
1242
1243 case ID_VIEW_REFRESH:
1244 RefreshTreeView(g_pChildWnd->hTreeWnd);
1245 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1246 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1247 break;
1248 /*case ID_OPTIONS_TOOLBAR:*/
1249 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1250 /* break;*/
1251 case ID_EDIT_NEW_KEY:
1252 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1253 break;
1254
1255 case ID_TREE_EXPANDBRANCH:
1256 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_EXPAND);
1257 break;
1258 case ID_TREE_COLLAPSEBRANCH:
1259 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_COLLAPSE);
1260 break;
1261 case ID_TREE_RENAME:
1262 SetFocus(g_pChildWnd->hTreeWnd);
1263 TreeView_EditLabel(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1264 break;
1265 case ID_TREE_DELETE:
1266 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), &hKeyRoot);
1267 if (keyPath == 0 || *keyPath == 0)
1268 {
1269 MessageBeep(MB_ICONHAND);
1270 }
1271 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1272 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1273 break;
1274 case ID_TREE_EXPORT:
1275 ExportRegistryFile(g_pChildWnd->hTreeWnd);
1276 break;
1277 case ID_TREE_PERMISSIONS:
1278 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), &hKeyRoot);
1279 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1280 break;
1281 case ID_SWITCH_PANELS:
1282 {
1283 BOOL bShiftDown = GetKeyState(VK_SHIFT) < 0;
1284 HWND hwndItem = GetNextDlgTabItem(g_pChildWnd->hWnd, GetFocus(), bShiftDown);
1285 if (hwndItem == g_pChildWnd->hAddressBarWnd)
1286 PostMessageW(hwndItem, EM_SETSEL, 0, -1);
1287 SetFocus(hwndItem);
1288 }
1289 break;
1290
1291 case ID_ADDRESS_FOCUS:
1292 SendMessageW(g_pChildWnd->hAddressBarWnd, EM_SETSEL, 0, -1);
1293 SetFocus(g_pChildWnd->hAddressBarWnd);
1294 break;
1295
1296 default:
1297 if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
1298 {
1299 HMENU hMenu;
1300 MENUITEMINFOW mii;
1301 WCHAR szFavorite[512];
1302
1303 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
1304
1305 memset(&mii, 0, sizeof(mii));
1306 mii.cbSize = sizeof(mii);
1307 mii.fMask = MIIM_TYPE;
1308 mii.fType = MFT_STRING;
1309 mii.dwTypeData = szFavorite;
1310 mii.cch = ARRAY_SIZE(szFavorite);
1311
1312 if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
1313 {
1314 ChooseFavorite(szFavorite);
1315 }
1316 }
1317 else if ((LOWORD(wParam) >= ID_TREE_SUGGESTION_MIN) && (LOWORD(wParam) <= ID_TREE_SUGGESTION_MAX))
1318 {
1319 WORD wID = LOWORD(wParam);
1320 LPCWSTR s = Suggestions;
1321 while(wID > ID_TREE_SUGGESTION_MIN)
1322 {
1323 if (*s)
1324 s += wcslen(s) + 1;
1325 wID--;
1326 }
1327 SelectNode(g_pChildWnd->hTreeWnd, s);
1328 }
1329 else
1330 {
1331 result = FALSE;
1332 }
1333 break;
1334 }
1335
1336 if(hKey)
1337 RegCloseKey(hKey);
1338 return result;
1339 }
1340
1341 /********************************************************************************
1342 *
1343 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1344 *
1345 * PURPOSE: Processes messages for the main frame window.
1346 *
1347 * WM_COMMAND - process the application menu
1348 * WM_DESTROY - post a quit message and return
1349 *
1350 */
1351
1352 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1353 {
1354 RECT rc;
1355 switch (message)
1356 {
1357 case WM_CREATE:
1358 // For now, the Help dialog item is disabled because of lacking of HTML Help support
1359 EnableMenuItem(GetMenu(hWnd), ID_HELP_HELPTOPICS, MF_BYCOMMAND | MF_GRAYED);
1360 GetClientRect(hWnd, &rc);
1361 CreateWindowExW(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
1362 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
1363 hWnd, (HMENU)0, hInst, 0);
1364 break;
1365 case WM_COMMAND:
1366 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1367 return DefWindowProcW(hWnd, message, wParam, lParam);
1368 break;
1369 case WM_ACTIVATE:
1370 if (LOWORD(hWnd) && g_pChildWnd)
1371 SetFocus(g_pChildWnd->hWnd);
1372 break;
1373 case WM_SIZE:
1374 resize_frame_client(hWnd);
1375 break;
1376 case WM_TIMER:
1377 break;
1378 case WM_INITMENU:
1379 OnInitMenu(hWnd);
1380 break;
1381 case WM_ENTERMENULOOP:
1382 OnEnterMenuLoop(hWnd);
1383 break;
1384 case WM_EXITMENULOOP:
1385 OnExitMenuLoop(hWnd);
1386 break;
1387 case WM_MENUSELECT:
1388 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1389 break;
1390 case WM_SYSCOLORCHANGE:
1391 /* Forward WM_SYSCOLORCHANGE to common controls */
1392 SendMessageW(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
1393 SendMessageW(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
1394 break;
1395 case WM_DESTROY:
1396 WinHelpW(hWnd, L"regedit", HELP_QUIT, 0);
1397 SaveSettings();
1398 PostQuitMessage(0);
1399 default:
1400 return DefWindowProcW(hWnd, message, wParam, lParam);
1401 }
1402 return 0;
1403 }