[REGEDIT]
[reactos.git] / reactos / 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 /********************************************************************************
24 * Global and Local Variables:
25 */
26
27 #define FAVORITES_MENU_POSITION 3
28
29 static WCHAR s_szFavoritesRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
30
31 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
32
33 /*******************************************************************************
34 * Local module support methods
35 */
36
37 static void resize_frame_rect(HWND hWnd, PRECT prect)
38 {
39 RECT rt;
40 /*
41 if (IsWindowVisible(hToolBar)) {
42 SendMessageW(hToolBar, WM_SIZE, 0, 0);
43 GetClientRect(hToolBar, &rt);
44 prect->top = rt.bottom+3;
45 prect->bottom -= rt.bottom+3;
46 }
47 */
48 if (IsWindowVisible(hStatusBar))
49 {
50 SetupStatusBar(hWnd, TRUE);
51 GetClientRect(hStatusBar, &rt);
52 prect->bottom -= rt.bottom;
53 }
54 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
55 }
56
57 static void resize_frame_client(HWND hWnd)
58 {
59 RECT rect;
60
61 GetClientRect(hWnd, &rect);
62 resize_frame_rect(hWnd, &rect);
63 }
64
65 /********************************************************************************/
66
67 static void OnInitMenu(HWND hWnd)
68 {
69 LONG lResult;
70 HKEY hKey = NULL;
71 DWORD dwIndex, cbValueName, cbValueData, dwType;
72 WCHAR szValueName[256];
73 BYTE abValueData[256];
74 static int s_nFavoriteMenuSubPos = -1;
75 HMENU hMenu;
76 BOOL bDisplayedAny = FALSE;
77
78 /* Find Favorites menu and clear it out */
79 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
80 if (!hMenu)
81 goto done;
82 if (s_nFavoriteMenuSubPos < 0)
83 {
84 s_nFavoriteMenuSubPos = GetMenuItemCount(hMenu);
85 }
86 else
87 {
88 while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION))
89 ;
90 }
91
92 lResult = RegOpenKeyW(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
93 if (lResult != ERROR_SUCCESS)
94 goto done;
95
96 dwIndex = 0;
97 do
98 {
99 cbValueName = COUNT_OF(szValueName);
100 cbValueData = sizeof(abValueData);
101 lResult = RegEnumValueW(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
102 if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
103 {
104 if (!bDisplayedAny)
105 {
106 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
107 bDisplayedAny = TRUE;
108 }
109 AppendMenu(hMenu, 0, ID_FAVORITES_MIN + GetMenuItemCount(hMenu), szValueName);
110 }
111 dwIndex++;
112 }
113 while(lResult == ERROR_SUCCESS);
114
115 done:
116 if (hKey)
117 RegCloseKey(hKey);
118 }
119
120 static void OnEnterMenuLoop(HWND hWnd)
121 {
122 int nParts;
123 UNREFERENCED_PARAMETER(hWnd);
124
125 /* Update the status bar pane sizes */
126 nParts = -1;
127 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
128 bInMenuLoop = TRUE;
129 SendMessageW(hStatusBar, SB_SETTEXTW, (WPARAM)0, (LPARAM)L"");
130 }
131
132 static void OnExitMenuLoop(HWND hWnd)
133 {
134 bInMenuLoop = FALSE;
135 /* Update the status bar pane sizes*/
136 SetupStatusBar(hWnd, TRUE);
137 UpdateStatusBar();
138 }
139
140 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
141 {
142 WCHAR str[100];
143
144 wcscpy(str, L"");
145 if (nFlags & MF_POPUP)
146 {
147 if (hSysMenu != GetMenu(hWnd))
148 {
149 if (nItemID == 2) nItemID = 5;
150 }
151 }
152 if (LoadStringW(hInst, nItemID, str, 100))
153 {
154 /* load appropriate string*/
155 LPWSTR lpsz = str;
156 /* first newline terminates actual string*/
157 lpsz = wcschr(lpsz, L'\n');
158 if (lpsz != NULL)
159 *lpsz = L'\0';
160 }
161 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
162 }
163
164 void SetupStatusBar(HWND hWnd, BOOL bResize)
165 {
166 RECT rc;
167 int nParts;
168 GetClientRect(hWnd, &rc);
169 nParts = rc.right;
170 /* nParts = -1;*/
171 if (bResize)
172 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
173 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
174 }
175
176 void UpdateStatusBar(void)
177 {
178 NMHDR nmhdr;
179 ZeroMemory(&nmhdr, sizeof(NMHDR));
180 nmhdr.code = TVN_SELCHANGED;
181 SendMessageW(g_pChildWnd->hWnd, WM_NOTIFY, (WPARAM)TREE_WINDOW, (LPARAM)&nmhdr);
182 }
183
184 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
185 {
186 BOOL vis = IsWindowVisible(hchild);
187 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
188
189 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
190 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
191 resize_frame_client(hWnd);
192 }
193
194 static BOOL CheckCommDlgError(HWND hWnd)
195 {
196 DWORD dwErrorCode = CommDlgExtendedError();
197 UNREFERENCED_PARAMETER(hWnd);
198 switch (dwErrorCode)
199 {
200 case CDERR_DIALOGFAILURE:
201 break;
202 case CDERR_FINDRESFAILURE:
203 break;
204 case CDERR_NOHINSTANCE:
205 break;
206 case CDERR_INITIALIZATION:
207 break;
208 case CDERR_NOHOOK:
209 break;
210 case CDERR_LOCKRESFAILURE:
211 break;
212 case CDERR_NOTEMPLATE:
213 break;
214 case CDERR_LOADRESFAILURE:
215 break;
216 case CDERR_STRUCTSIZE:
217 break;
218 case CDERR_LOADSTRFAILURE:
219 break;
220 case FNERR_BUFFERTOOSMALL:
221 break;
222 case CDERR_MEMALLOCFAILURE:
223 break;
224 case FNERR_INVALIDFILENAME:
225 break;
226 case CDERR_MEMLOCKFAILURE:
227 break;
228 case FNERR_SUBCLASSFAILURE:
229 break;
230 default:
231 break;
232 }
233 return TRUE;
234 }
235
236 WCHAR FileNameBuffer[_MAX_PATH];
237 WCHAR FileTitleBuffer[_MAX_PATH];
238
239 typedef struct
240 {
241 UINT DisplayID;
242 UINT FilterID;
243 } FILTERPAIR, *PFILTERPAIR;
244
245 void
246 BuildFilterStrings(WCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
247 {
248 int i, c;
249
250 c = 0;
251 for(i = 0; i < PairCount; i++)
252 {
253 c += LoadStringW(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(WCHAR));
254 Filter[++c] = L'\0';
255 c += LoadStringW(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(WCHAR));
256 Filter[++c] = L'\0';
257 }
258 Filter[++c] = L'\0';
259 }
260
261 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
262 {
263 FILTERPAIR FilterPairs[4];
264 static WCHAR Filter[1024];
265
266 memset(pofn, 0, sizeof(OPENFILENAME));
267 pofn->lStructSize = sizeof(OPENFILENAME);
268 pofn->hwndOwner = hWnd;
269 pofn->hInstance = hInst;
270
271 /* create filter string */
272 FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
273 FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
274 FilterPairs[1].DisplayID = IDS_FLT_HIVFILES;
275 FilterPairs[1].FilterID = IDS_FLT_HIVFILES_FLT;
276 FilterPairs[2].DisplayID = IDS_FLT_REGEDIT4;
277 FilterPairs[2].FilterID = IDS_FLT_REGEDIT4_FLT;
278 FilterPairs[3].DisplayID = IDS_FLT_ALLFILES;
279 FilterPairs[3].FilterID = IDS_FLT_ALLFILES_FLT;
280 BuildFilterStrings(Filter, FilterPairs, COUNT_OF(FilterPairs));
281
282 pofn->lpstrFilter = Filter;
283 pofn->lpstrFile = FileNameBuffer;
284 pofn->nMaxFile = _MAX_PATH;
285 pofn->lpstrFileTitle = FileTitleBuffer;
286 pofn->nMaxFileTitle = _MAX_PATH;
287 pofn->Flags = OFN_HIDEREADONLY;
288 pofn->lpstrDefExt = L"reg";
289 return TRUE;
290 }
291
292 static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
293 {
294 static LPWSTR sKey = NULL;
295 static INT sLength = 0;
296 switch(uMsg)
297 {
298 case WM_INITDIALOG:
299 sKey = (LPWSTR)lParam;
300 sLength = 128; /* FIXME: Ugly hack! */
301 case WM_COMMAND:
302 switch(LOWORD(wParam))
303 {
304 case IDOK:
305 if(GetDlgItemTextW(hWndDlg, IDC_EDIT_KEY, sKey, sLength))
306 return EndDialog(hWndDlg, -1);
307 else
308 return EndDialog(hWndDlg, 0);
309 case IDCANCEL:
310 return EndDialog(hWndDlg, 0);
311 }
312 break;
313 }
314 return FALSE;
315 }
316
317 static BOOL EnablePrivilege(LPCWSTR lpszPrivilegeName, LPCWSTR lpszSystemName, BOOL bEnablePrivilege)
318 {
319 BOOL bRet = FALSE;
320 HANDLE hToken = NULL;
321
322 if (OpenProcessToken(GetCurrentProcess(),
323 TOKEN_ADJUST_PRIVILEGES,
324 &hToken))
325 {
326 TOKEN_PRIVILEGES tp;
327
328 tp.PrivilegeCount = 1;
329 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
330
331 if (LookupPrivilegeValueW(lpszSystemName,
332 lpszPrivilegeName,
333 &tp.Privileges[0].Luid))
334 {
335 bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
336
337 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
338 bRet = FALSE;
339 }
340
341 CloseHandle(hToken);
342 }
343
344 return bRet;
345 }
346
347 static BOOL LoadHive(HWND hWnd)
348 {
349 OPENFILENAME ofn;
350 WCHAR Caption[128];
351 LPCWSTR pszKeyPath;
352 WCHAR xPath[128];
353 HKEY hRootKey;
354 WCHAR Filter[1024];
355 FILTERPAIR filter;
356 /* get the item key to load the hive in */
357 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
358 /* initialize the "open file" dialog */
359 InitOpenFileName(hWnd, &ofn);
360 /* build the "All Files" filter up */
361 filter.DisplayID = IDS_FLT_ALLFILES;
362 filter.FilterID = IDS_FLT_ALLFILES_FLT;
363 BuildFilterStrings(Filter, &filter, sizeof(filter));
364 ofn.lpstrFilter = Filter;
365 /* load and set the caption and flags for dialog */
366 LoadStringW(hInst, IDS_LOAD_HIVE, Caption, COUNT_OF(Caption));
367 ofn.lpstrTitle = Caption;
368 ofn.Flags |= OFN_ENABLESIZING;
369 /* ofn.lCustData = ;*/
370 /* now load the hive */
371 if (GetOpenFileName(&ofn))
372 {
373 if(DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_LOADHIVE), hWnd, &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
374 {
375 LONG regLoadResult;
376
377 /* Enable the 'restore' privilege, load the hive, disable the privilege */
378 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
379 regLoadResult = RegLoadKeyW(hRootKey, xPath, ofn.lpstrFile);
380 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
381
382 if(regLoadResult == ERROR_SUCCESS)
383 {
384 /* refresh tree and list views */
385 RefreshTreeView(g_pChildWnd->hTreeWnd);
386 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
387 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
388 }
389 else
390 {
391 ErrorMessageBox(hWnd, Caption, regLoadResult);
392 return FALSE;
393 }
394 }
395 }
396 else
397 {
398 CheckCommDlgError(hWnd);
399 }
400 return TRUE;
401 }
402
403 static BOOL UnloadHive(HWND hWnd)
404 {
405 WCHAR Caption[128];
406 LPCWSTR pszKeyPath;
407 HKEY hRootKey;
408 LONG regUnloadResult;
409
410 /* get the item key to unload */
411 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
412 /* load and set the caption and flags for dialog */
413 LoadStringW(hInst, IDS_UNLOAD_HIVE, Caption, COUNT_OF(Caption));
414
415 /* Enable the 'restore' privilege, unload the hive, disable the privilege */
416 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
417 regUnloadResult = RegUnLoadKeyW(hRootKey, pszKeyPath);
418 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
419
420 if(regUnloadResult == ERROR_SUCCESS)
421 {
422 /* refresh tree and list views */
423 RefreshTreeView(g_pChildWnd->hTreeWnd);
424 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
425 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
426 }
427 else
428 {
429 ErrorMessageBox(hWnd, Caption, regUnloadResult);
430 return FALSE;
431 }
432 return TRUE;
433 }
434
435 static BOOL ImportRegistryFile(HWND hWnd)
436 {
437 BOOL bRet = FALSE;
438 OPENFILENAME ofn;
439 WCHAR Caption[128], szTitle[256], szText[256];
440 HKEY hKeyRoot;
441 LPCWSTR pszKeyPath;
442
443 /* Figure out in which key path we are importing */
444 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
445
446 InitOpenFileName(hWnd, &ofn);
447 LoadStringW(hInst, IDS_IMPORT_REG_FILE, Caption, COUNT_OF(Caption));
448 ofn.lpstrTitle = Caption;
449 ofn.Flags |= OFN_ENABLESIZING;
450 /* ofn.lCustData = ;*/
451 if (GetOpenFileName(&ofn))
452 {
453 /* Look at the extension of the file to determine its type */
454 if (ofn.nFileExtension >= 1 &&
455 wcsicmp(ofn.lpstrFile + ofn.nFileExtension, L"reg") == 0) /* REGEDIT4 or Windows Registry Editor Version 5.00 */
456 {
457 /* Open the file */
458 FILE *fp = _wfopen(ofn.lpstrFile, L"r");
459
460 /* Import it */
461 if (fp == NULL || !import_registry_file(fp))
462 {
463 LPSTR p = GetMultiByteString(ofn.lpstrFile);
464 fwprintf(stderr, L"Can't open file \"%s\"\n", p);
465 HeapFree(GetProcessHeap(), 0, p);
466 bRet = FALSE;
467 }
468 else
469 {
470 /* Show successful import */
471 LoadStringW(hInst, IDS_APP_TITLE, szTitle, COUNT_OF(szTitle));
472 LoadStringW(hInst, IDS_IMPORT_OK, szText, COUNT_OF(szText));
473 MessageBoxW(NULL, szText, szTitle, MB_OK);
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, COUNT_OF(szTitle));
483 LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_MSG, szText, COUNT_OF(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];
585 WCHAR Caption[128];
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, COUNT_OF(ExportKeyPath), hKeyRoot, pszKeyPath);
592
593 InitOpenFileName(hWnd, &ofn);
594 LoadStringW(hInst, IDS_EXPORT_REG_FILE, Caption, COUNT_OF(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 LPSTR p = GetMultiByteString(ofn.lpstrFile);
668 fwprintf(stderr, L"Can't open file \"%s\"\n", p);
669 HeapFree(GetProcessHeap(), 0, p);
670 bRet = FALSE;
671 }
672 else
673 {
674 bRet = TRUE;
675 }
676
677 break;
678 }
679 }
680 }
681 else
682 {
683 CheckCommDlgError(hWnd);
684 }
685
686 return bRet;
687 }
688
689 BOOL PrintRegistryHive(HWND hWnd, LPWSTR path)
690 {
691 #if 1
692 PRINTDLG pd;
693 UNREFERENCED_PARAMETER(path);
694
695 ZeroMemory(&pd, sizeof(PRINTDLG));
696 pd.lStructSize = sizeof(PRINTDLG);
697 pd.hwndOwner = hWnd;
698 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
699 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
700 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
701 pd.nCopies = 1;
702 pd.nFromPage = 0xFFFF;
703 pd.nToPage = 0xFFFF;
704 pd.nMinPage = 1;
705 pd.nMaxPage = 0xFFFF;
706 if (PrintDlg(&pd))
707 {
708 /* GDI calls to render output. */
709 DeleteDC(pd.hDC); /* Delete DC when done.*/
710 }
711 #else
712 HRESULT hResult;
713 PRINTDLGEX pd;
714
715 hResult = PrintDlgEx(&pd);
716 if (hResult == S_OK)
717 {
718 switch (pd.dwResultAction)
719 {
720 case PD_RESULT_APPLY:
721 /*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. */
722 break;
723 case PD_RESULT_CANCEL:
724 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
725 break;
726 case PD_RESULT_PRINT:
727 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
728 break;
729 default:
730 break;
731 }
732 }
733 else
734 {
735 switch (hResult)
736 {
737 case E_OUTOFMEMORY:
738 /*Insufficient memory. */
739 break;
740 case E_INVALIDARG:
741 /* One or more arguments are invalid. */
742 break;
743 case E_POINTER:
744 /*Invalid pointer. */
745 break;
746 case E_HANDLE:
747 /*Invalid handle. */
748 break;
749 case E_FAIL:
750 /*Unspecified error. */
751 break;
752 default:
753 break;
754 }
755 return FALSE;
756 }
757 #endif
758 return TRUE;
759 }
760
761 static void ChooseFavorite(LPCWSTR pszFavorite)
762 {
763 HKEY hKey = NULL;
764 WCHAR szFavoritePath[512];
765 DWORD cbData, dwType;
766
767 if (RegOpenKeyExW(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
768 goto done;
769
770 cbData = (sizeof(szFavoritePath) / sizeof(szFavoritePath[0])) - 1;
771 memset(szFavoritePath, 0, sizeof(szFavoritePath));
772 if (RegQueryValueExW(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
773 goto done;
774
775 if (dwType == REG_SZ)
776 SelectNode(g_pChildWnd->hTreeWnd, szFavoritePath);
777
778 done:
779 if (hKey)
780 RegCloseKey(hKey);
781 }
782
783 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCWSTR keyName)
784 {
785 BOOL bClipboardOpened = FALSE;
786 BOOL bSuccess = FALSE;
787 WCHAR szBuffer[512];
788 HGLOBAL hGlobal;
789 LPWSTR s;
790
791 if (!OpenClipboard(hWnd))
792 goto done;
793 bClipboardOpened = TRUE;
794
795 if (!EmptyClipboard())
796 goto done;
797
798 if (!GetKeyName(szBuffer, COUNT_OF(szBuffer), hRootKey, keyName))
799 goto done;
800
801 hGlobal = GlobalAlloc(GMEM_MOVEABLE, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
802 if (!hGlobal)
803 goto done;
804
805 s = GlobalLock(hGlobal);
806 wcscpy(s, szBuffer);
807 GlobalUnlock(hGlobal);
808
809 SetClipboardData(CF_UNICODETEXT, hGlobal);
810 bSuccess = TRUE;
811
812 done:
813 if (bClipboardOpened)
814 CloseClipboard();
815 return bSuccess;
816 }
817
818 static BOOL CreateNewValue(HKEY hRootKey, LPCWSTR pszKeyPath, DWORD dwType)
819 {
820 WCHAR szNewValueFormat[128];
821 WCHAR szNewValue[128];
822 int iIndex = 1;
823 BYTE data[128];
824 DWORD dwExistingType, cbData;
825 LONG lResult;
826 HKEY hKey;
827 LVFINDINFO lvfi;
828
829 if (RegOpenKeyExW(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
830 &hKey) != ERROR_SUCCESS)
831 return FALSE;
832
833 LoadStringW(hInst, IDS_NEW_VALUE, szNewValueFormat, COUNT_OF(szNewValueFormat));
834
835 do
836 {
837 wsprintf(szNewValue, szNewValueFormat, iIndex++);
838 cbData = sizeof(data);
839 lResult = RegQueryValueExW(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
840 }
841 while(lResult == ERROR_SUCCESS);
842
843 switch(dwType)
844 {
845 case REG_DWORD:
846 cbData = sizeof(DWORD);
847 break;
848 case REG_SZ:
849 case REG_EXPAND_SZ:
850 cbData = sizeof(WCHAR);
851 break;
852 case REG_MULTI_SZ:
853 cbData = sizeof(WCHAR) * 2;
854 break;
855 case REG_QWORD:
856 cbData = sizeof(DWORD) * 2;
857 break;
858 default:
859 cbData = 0;
860 break;
861 }
862 memset(data, 0, cbData);
863 lResult = RegSetValueExW(hKey, szNewValue, 0, dwType, data, cbData);
864 RegCloseKey(hKey);
865 if (lResult != ERROR_SUCCESS)
866 {
867 return FALSE;
868 }
869
870 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
871
872 /* locate the newly added value, and get ready to rename it */
873 memset(&lvfi, 0, sizeof(lvfi));
874 lvfi.flags = LVFI_STRING;
875 lvfi.psz = szNewValue;
876 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
877 if (iIndex >= 0)
878 (void)ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
879
880 return TRUE;
881 }
882
883 static HRESULT
884 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
885 {
886 HRESULT hRet;
887
888 *pDsObjectPicker = NULL;
889
890 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
891 NULL,
892 CLSCTX_INPROC_SERVER,
893 &IID_IDsObjectPicker,
894 (LPVOID*)pDsObjectPicker);
895 if (SUCCEEDED(hRet))
896 {
897 DSOP_INIT_INFO InitInfo;
898 static DSOP_SCOPE_INIT_INFO Scopes[] =
899 {
900 {
901 sizeof(DSOP_SCOPE_INIT_INFO),
902 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
903 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
904 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
905 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
906 0,
907 {
908 {
909 DSOP_FILTER_COMPUTERS,
910 0,
911 0
912 },
913 DSOP_DOWNLEVEL_FILTER_COMPUTERS
914 },
915 NULL,
916 NULL,
917 S_OK
918 },
919 };
920
921 InitInfo.cbSize = sizeof(InitInfo);
922 InitInfo.pwzTargetComputer = NULL;
923 InitInfo.cDsScopeInfos = COUNT_OF(Scopes);
924 InitInfo.aDsScopeInfos = Scopes;
925 InitInfo.flOptions = 0;
926 InitInfo.cAttributesToFetch = 0;
927 InitInfo.apwzAttributeNames = NULL;
928
929 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
930 &InitInfo);
931
932 if (FAILED(hRet))
933 {
934 /* delete the object picker in case initialization failed! */
935 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
936 }
937 }
938
939 return hRet;
940 }
941
942 static HRESULT
943 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
944 IN HWND hwndParent OPTIONAL,
945 OUT LPWSTR lpBuffer,
946 IN UINT uSize)
947 {
948 IDataObject *pdo = NULL;
949 HRESULT hRet;
950
951 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
952 hwndParent,
953 &pdo);
954 if (hRet == S_OK)
955 {
956 STGMEDIUM stm;
957 FORMATETC fe;
958
959 fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormatW(CFSTR_DSOP_DS_SELECTION_LIST);
960 fe.ptd = NULL;
961 fe.dwAspect = DVASPECT_CONTENT;
962 fe.lindex = -1;
963 fe.tymed = TYMED_HGLOBAL;
964
965 hRet = pdo->lpVtbl->GetData(pdo,
966 &fe,
967 &stm);
968 if (SUCCEEDED(hRet))
969 {
970 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
971 if (SelectionList != NULL)
972 {
973 if (SelectionList->cItems == 1)
974 {
975 size_t nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
976 if (nlen >= uSize)
977 {
978 nlen = uSize - 1;
979 }
980
981 memcpy(lpBuffer,
982 SelectionList->aDsSelection[0].pwzName,
983 nlen * sizeof(WCHAR));
984
985 lpBuffer[nlen] = L'\0';
986 }
987
988 GlobalUnlock(stm.hGlobal);
989 }
990
991 ReleaseStgMedium(&stm);
992 }
993
994 pdo->lpVtbl->Release(pdo);
995 }
996
997 return hRet;
998 }
999
1000 static VOID
1001 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
1002 {
1003 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
1004 }
1005
1006 /*******************************************************************************
1007 *
1008 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
1009 *
1010 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
1011 *
1012 */
1013 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1014 {
1015 HKEY hKeyRoot = 0, hKey = 0;
1016 LPCWSTR keyPath;
1017 LPCWSTR valueName;
1018 BOOL result = TRUE;
1019 REGSAM regsam = KEY_READ;
1020 LONG lRet;
1021 int item;
1022
1023 UNREFERENCED_PARAMETER(lParam);
1024 UNREFERENCED_PARAMETER(message);
1025
1026 switch (LOWORD(wParam))
1027 {
1028 case ID_REGISTRY_LOADHIVE:
1029 LoadHive(hWnd);
1030 return TRUE;
1031 case ID_REGISTRY_UNLOADHIVE:
1032 UnloadHive(hWnd);
1033 return TRUE;
1034 case ID_REGISTRY_IMPORTREGISTRYFILE:
1035 ImportRegistryFile(hWnd);
1036 return TRUE;
1037 case ID_REGISTRY_EXPORTREGISTRYFILE:
1038 ExportRegistryFile(hWnd);
1039 return TRUE;
1040 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
1041 {
1042 IDsObjectPicker *ObjectPicker;
1043 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1044 HRESULT hRet;
1045
1046 hRet = CoInitialize(NULL);
1047 if (SUCCEEDED(hRet))
1048 {
1049 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
1050 if (SUCCEEDED(hRet))
1051 {
1052 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
1053 hWnd,
1054 szComputerName,
1055 COUNT_OF(szComputerName));
1056 if (hRet == S_OK)
1057 {
1058 /* FIXME - connect to the registry */
1059 }
1060
1061 FreeObjectPicker(ObjectPicker);
1062 }
1063
1064 CoUninitialize();
1065 }
1066
1067 return TRUE;
1068 }
1069 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
1070 return TRUE;
1071 case ID_REGISTRY_PRINT:
1072 PrintRegistryHive(hWnd, L"");
1073 return TRUE;
1074 case ID_REGISTRY_EXIT:
1075 DestroyWindow(hWnd);
1076 return TRUE;
1077 case ID_VIEW_STATUSBAR:
1078 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1079 return TRUE;
1080 case ID_HELP_HELPTOPICS:
1081 WinHelpW(hWnd, getAppName(), HELP_FINDER, 0);
1082 return TRUE;
1083 case ID_HELP_ABOUT:
1084 ShowAboutBox(hWnd);
1085 return TRUE;
1086 case ID_VIEW_SPLIT:
1087 {
1088 RECT rt;
1089 POINT pt, pts;
1090 GetClientRect(g_pChildWnd->hWnd, &rt);
1091 pt.x = rt.left + g_pChildWnd->nSplitPos;
1092 pt.y = (rt.bottom / 2);
1093 pts = pt;
1094 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
1095 {
1096 SetCursorPos(pts.x, pts.y);
1097 SetCursor(LoadCursorW(0, IDC_SIZEWE));
1098 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1099 }
1100 return TRUE;
1101 }
1102 case ID_EDIT_RENAME:
1103 case ID_EDIT_MODIFY:
1104 case ID_EDIT_MODIFY_BIN:
1105 case ID_EDIT_DELETE:
1106 regsam |= KEY_WRITE;
1107 break;
1108 }
1109
1110 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1111 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
1112 if (keyPath)
1113 {
1114 lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, regsam, &hKey);
1115 if (lRet != ERROR_SUCCESS) hKey = 0;
1116 }
1117
1118 switch (LOWORD(wParam))
1119 {
1120 case ID_EDIT_MODIFY:
1121 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
1122 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1123 break;
1124 case ID_EDIT_MODIFY_BIN:
1125 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
1126 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1127 break;
1128 case ID_EDIT_RENAME:
1129 if (GetFocus() == g_pChildWnd->hListWnd)
1130 {
1131 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
1132 {
1133 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
1134 if(item > -1)
1135 {
1136 (void)ListView_EditLabel(g_pChildWnd->hListWnd, item);
1137 }
1138 }
1139 }
1140 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1141 {
1142 /* Get focused entry of treeview (if any) */
1143 HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
1144 if (hItem != NULL)
1145 (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, hItem);
1146 }
1147 break;
1148 case ID_EDIT_DELETE:
1149 {
1150 if (GetFocus() == g_pChildWnd->hListWnd)
1151 {
1152 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
1153 if(nSelected >= 1)
1154 {
1155 WCHAR msg[128], caption[128];
1156 LoadStringW(hInst, IDS_QUERY_DELETE_CONFIRM, caption, COUNT_OF(caption));
1157 LoadStringW(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, COUNT_OF(msg));
1158 if(MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
1159 {
1160 int ni, errs;
1161
1162 item = -1;
1163 errs = 0;
1164 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
1165 {
1166 valueName = GetValueName(g_pChildWnd->hListWnd, item);
1167 if(RegDeleteValueW(hKey, valueName) != ERROR_SUCCESS)
1168 {
1169 errs++;
1170 }
1171 item = ni;
1172 }
1173
1174 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1175 if(errs > 0)
1176 {
1177 LoadStringW(hInst, IDS_ERR_DELVAL_CAPTION, caption, COUNT_OF(caption));
1178 LoadStringW(hInst, IDS_ERR_DELETEVALUE, msg, COUNT_OF(msg));
1179 MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
1180 }
1181 }
1182 }
1183 }
1184 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1185 {
1186 if (keyPath == 0 || *keyPath == 0)
1187 {
1188 MessageBeep(MB_ICONHAND);
1189 }
1190 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1191 {
1192 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1193 RefreshTreeView(g_pChildWnd->hTreeWnd);
1194 }
1195 }
1196 break;
1197 }
1198 case ID_EDIT_NEW_STRINGVALUE:
1199 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
1200 break;
1201 case ID_EDIT_NEW_BINARYVALUE:
1202 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
1203 break;
1204 case ID_EDIT_NEW_DWORDVALUE:
1205 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
1206 break;
1207 case ID_EDIT_NEW_MULTISTRINGVALUE:
1208 CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
1209 break;
1210 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
1211 CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
1212 break;
1213 case ID_EDIT_FIND:
1214 FindDialog(hWnd);
1215 break;
1216 case ID_EDIT_FINDNEXT:
1217 FindNext(hWnd);
1218 break;
1219 case ID_EDIT_COPYKEYNAME:
1220 CopyKeyName(hWnd, hKeyRoot, keyPath);
1221 break;
1222 case ID_EDIT_PERMISSIONS:
1223 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1224 break;
1225 case ID_REGISTRY_PRINTERSETUP:
1226 /*PRINTDLG pd;*/
1227 /*PrintDlg(&pd);*/
1228 /*PAGESETUPDLG psd;*/
1229 /*PageSetupDlg(&psd);*/
1230 break;
1231 case ID_REGISTRY_OPENLOCAL:
1232 break;
1233
1234 case ID_VIEW_REFRESH:
1235 RefreshTreeView(g_pChildWnd->hTreeWnd);
1236 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1237 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1238 break;
1239 /*case ID_OPTIONS_TOOLBAR:*/
1240 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1241 /* break;*/
1242 case ID_EDIT_NEW_KEY:
1243 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1244 break;
1245 default:
1246 if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
1247 {
1248 HMENU hMenu;
1249 MENUITEMINFO mii;
1250 WCHAR szFavorite[512];
1251
1252 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
1253
1254 memset(&mii, 0, sizeof(mii));
1255 mii.cbSize = sizeof(mii);
1256 mii.fMask = MIIM_TYPE;
1257 mii.fType = MFT_STRING;
1258 mii.dwTypeData = szFavorite;
1259 mii.cch = COUNT_OF(szFavorite);
1260
1261 if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
1262 {
1263 ChooseFavorite(szFavorite);
1264 }
1265 }
1266 else
1267 {
1268 result = FALSE;
1269 }
1270 break;
1271 }
1272
1273 if(hKey)
1274 RegCloseKey(hKey);
1275 return result;
1276 }
1277
1278 /********************************************************************************
1279 *
1280 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1281 *
1282 * PURPOSE: Processes messages for the main frame window.
1283 *
1284 * WM_COMMAND - process the application menu
1285 * WM_DESTROY - post a quit message and return
1286 *
1287 */
1288
1289 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1290 {
1291 switch (message)
1292 {
1293 case WM_CREATE:
1294 CreateWindowExW(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
1295 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1296 hWnd, (HMENU)0, hInst, 0);
1297 break;
1298 case WM_COMMAND:
1299 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1300 return DefWindowProcW(hWnd, message, wParam, lParam);
1301 break;
1302 case WM_ACTIVATE:
1303 if (LOWORD(hWnd))
1304 SetFocus(g_pChildWnd->hWnd);
1305 break;
1306 case WM_SIZE:
1307 resize_frame_client(hWnd);
1308 break;
1309 case WM_TIMER:
1310 break;
1311 case WM_INITMENU:
1312 OnInitMenu(hWnd);
1313 break;
1314 case WM_ENTERMENULOOP:
1315 OnEnterMenuLoop(hWnd);
1316 break;
1317 case WM_EXITMENULOOP:
1318 OnExitMenuLoop(hWnd);
1319 break;
1320 case WM_MENUSELECT:
1321 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1322 break;
1323 case WM_SYSCOLORCHANGE:
1324 /* Forward WM_SYSCOLORCHANGE to common controls */
1325 SendMessageW(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
1326 SendMessageW(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
1327 break;
1328 case WM_DESTROY:
1329 WinHelpW(hWnd, getAppName(), HELP_QUIT, 0);
1330 SaveSettings();
1331 PostQuitMessage(0);
1332 default:
1333 return DefWindowProcW(hWnd, message, wParam, lParam);
1334 }
1335 return 0;
1336 }