[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 TCHAR s_szFavoritesRegKey[] = _T("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 SendMessage(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 TCHAR 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 = RegOpenKey(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 = RegEnumValue(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 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
128 bInMenuLoop = TRUE;
129 SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
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 TCHAR str[100];
143
144 _tcscpy(str, _T(""));
145 if (nFlags & MF_POPUP)
146 {
147 if (hSysMenu != GetMenu(hWnd))
148 {
149 if (nItemID == 2) nItemID = 5;
150 }
151 }
152 if (LoadString(hInst, nItemID, str, 100))
153 {
154 /* load appropriate string*/
155 LPTSTR lpsz = str;
156 /* first newline terminates actual string*/
157 lpsz = _tcschr(lpsz, _T('\n'));
158 if (lpsz != NULL)
159 *lpsz = '\0';
160 }
161 SendMessage(hStatusBar, SB_SETTEXT, 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 SendMessage(hStatusBar, WM_SIZE, 0, 0);
173 SendMessage(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 SendMessage(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 TCHAR FileNameBuffer[_MAX_PATH];
237 TCHAR FileTitleBuffer[_MAX_PATH];
238
239 typedef struct
240 {
241 UINT DisplayID;
242 UINT FilterID;
243 } FILTERPAIR, *PFILTERPAIR;
244
245 void
246 BuildFilterStrings(TCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
247 {
248 int i, c;
249
250 c = 0;
251 for(i = 0; i < PairCount; i++)
252 {
253 c += LoadString(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(TCHAR));
254 Filter[++c] = '\0';
255 c += LoadString(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(TCHAR));
256 Filter[++c] = '\0';
257 }
258 Filter[++c] = '\0';
259 }
260
261 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
262 {
263 FILTERPAIR FilterPairs[3];
264 static TCHAR 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_REGEDIT4;
275 FilterPairs[1].FilterID = IDS_FLT_REGEDIT4_FLT;
276 FilterPairs[2].DisplayID = IDS_FLT_ALLFILES;
277 FilterPairs[2].FilterID = IDS_FLT_ALLFILES_FLT;
278 BuildFilterStrings(Filter, FilterPairs, sizeof(FilterPairs) / sizeof(FILTERPAIR));
279
280 pofn->lpstrFilter = Filter;
281 pofn->lpstrFile = FileNameBuffer;
282 pofn->nMaxFile = _MAX_PATH;
283 pofn->lpstrFileTitle = FileTitleBuffer;
284 pofn->nMaxFileTitle = _MAX_PATH;
285 pofn->Flags = OFN_HIDEREADONLY;
286 pofn->lpstrDefExt = TEXT("reg");
287 return TRUE;
288 }
289
290 static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
291 {
292 static LPTSTR sKey = NULL;
293 static INT sLength = 0;
294 switch(uMsg)
295 {
296 case WM_INITDIALOG:
297 sKey = (LPTSTR)lParam;
298 sLength = 128; /* FIXME: Ugly hack! */
299 case WM_COMMAND:
300 switch(LOWORD(wParam))
301 {
302 case IDOK:
303 if(GetDlgItemText(hWndDlg, IDC_EDIT_KEY, sKey, sLength))
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(LPCTSTR lpszPrivilegeName, LPCTSTR 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 (LookupPrivilegeValue(lpszSystemName,
330 lpszPrivilegeName,
331 &tp.Privileges[0].Luid))
332 {
333 bRet = AdjustTokenPrivileges(hToken,
334 FALSE,
335 &tp,
336 sizeof(tp),
337 NULL,
338 NULL);
339 }
340
341 CloseHandle(hToken);
342 }
343
344 return bRet;
345 }
346
347 static BOOL LoadHive(HWND hWnd)
348 {
349 OPENFILENAME ofn;
350 TCHAR Caption[128];
351 LPCTSTR pszKeyPath;
352 TCHAR xPath[128];
353 HKEY hRootKey;
354 TCHAR 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 LoadString(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(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOADHIVE), hWnd, &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
374 {
375 LONG regLoadResult;
376
377 /* Enable the required privileges */
378 EnablePrivilege(SE_BACKUP_NAME, NULL, TRUE);
379 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
380
381 /* Load the hive */
382 regLoadResult = RegLoadKey(hRootKey, xPath, ofn.lpstrFile);
383
384 /* Disable the privileges */
385 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
386 EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
387
388 if(regLoadResult == ERROR_SUCCESS)
389 {
390 /* refresh tree and list views */
391 RefreshTreeView(g_pChildWnd->hTreeWnd);
392 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
393 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
394 }
395 else
396 {
397 ErrorMessageBox(hWnd, Caption, regLoadResult);
398 return FALSE;
399 }
400 }
401 }
402 else
403 {
404 CheckCommDlgError(hWnd);
405 }
406 return TRUE;
407 }
408
409 static BOOL UnloadHive(HWND hWnd)
410 {
411 TCHAR Caption[128];
412 LPCTSTR pszKeyPath;
413 HKEY hRootKey;
414 LONG regUnloadResult;
415
416 /* get the item key to unload */
417 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
418 /* load and set the caption and flags for dialog */
419 LoadString(hInst, IDS_UNLOAD_HIVE, Caption, COUNT_OF(Caption));
420
421 /* Enable the required privileges */
422 EnablePrivilege(SE_BACKUP_NAME, NULL, TRUE);
423 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
424
425 /* Unload the hive */
426 regUnloadResult = RegUnLoadKey(hRootKey, pszKeyPath);
427
428 /* Disable the privileges */
429 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
430 EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
431
432 if(regUnloadResult == ERROR_SUCCESS)
433 {
434 /* refresh tree and list views */
435 RefreshTreeView(g_pChildWnd->hTreeWnd);
436 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
437 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
438 }
439 else
440 {
441 ErrorMessageBox(hWnd, Caption, regUnloadResult);
442 return FALSE;
443 }
444 return TRUE;
445 }
446
447 static BOOL ImportRegistryFile(HWND hWnd)
448 {
449 OPENFILENAME ofn;
450 TCHAR Caption[128], szTitle[256], szText[256];
451 LPCTSTR pszKeyPath;
452 HKEY hRootKey;
453
454 InitOpenFileName(hWnd, &ofn);
455 LoadString(hInst, IDS_IMPORT_REG_FILE, Caption, COUNT_OF(Caption));
456 ofn.lpstrTitle = Caption;
457 ofn.Flags |= OFN_ENABLESIZING;
458 /* ofn.lCustData = ;*/
459 if (GetOpenFileName(&ofn))
460 {
461 FILE *fp = _wfopen(ofn.lpstrFile, L"r");
462 if (fp == NULL || !import_registry_file(fp))
463 {
464 LPSTR p = GetMultiByteString(ofn.lpstrFile);
465 fprintf(stderr, "Can't open file \"%s\"\n", p);
466 HeapFree(GetProcessHeap(), 0, p);
467 if (fp != NULL)
468 fclose(fp);
469 return FALSE;
470 }
471 LoadString(hInst, IDS_APP_TITLE, szTitle, sizeof(szTitle));
472 LoadString(hInst, IDS_IMPORTED_OK, szText, sizeof(szTitle));
473 /* show successful import */
474 MessageBox(NULL, szText, szTitle, MB_OK);
475 fclose(fp);
476 }
477 else
478 {
479 CheckCommDlgError(hWnd);
480 }
481
482 RefreshTreeView(g_pChildWnd->hTreeWnd);
483 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
484 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
485
486 return TRUE;
487 }
488
489 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
490 {
491 HWND hwndExportAll;
492 HWND hwndExportBranch;
493 HWND hwndExportBranchText;
494 UINT_PTR iResult = 0;
495 OPENFILENAME *pOfn;
496 LPTSTR pszSelectedKey;
497 OFNOTIFY *pOfnNotify;
498
499 UNREFERENCED_PARAMETER(wParam);
500
501 switch(uiMsg)
502 {
503 case WM_INITDIALOG:
504 pOfn = (OPENFILENAME *) lParam;
505 pszSelectedKey = (LPTSTR) pOfn->lCustData;
506
507 hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
508 if (hwndExportAll)
509 SendMessage(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
510
511 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
512 if (hwndExportBranch)
513 SendMessage(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
514
515 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
516 if (hwndExportBranchText)
517 SetWindowText(hwndExportBranchText, pszSelectedKey);
518 break;
519
520 case WM_NOTIFY:
521 if (((NMHDR *) lParam)->code == CDN_FILEOK)
522 {
523 pOfnNotify = (OFNOTIFY *) lParam;
524 pszSelectedKey = (LPTSTR) pOfnNotify->lpOFN->lCustData;
525
526 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
527 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
528 if (hwndExportBranch && hwndExportBranchText
529 && (SendMessage(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
530 {
531 GetWindowText(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
532 }
533 else
534 {
535 pszSelectedKey[0] = '\0';
536 }
537 }
538 break;
539 }
540 return iResult;
541 }
542
543 BOOL ExportRegistryFile(HWND hWnd)
544 {
545 OPENFILENAME ofn;
546 TCHAR ExportKeyPath[_MAX_PATH];
547 TCHAR Caption[128];
548 HKEY hKeyRoot;
549 LPCTSTR pszKeyPath;
550
551 /* Figure out which key path we are exporting */
552 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
553 GetKeyName(ExportKeyPath, COUNT_OF(ExportKeyPath), hKeyRoot, pszKeyPath);
554
555 InitOpenFileName(hWnd, &ofn);
556 LoadString(hInst, IDS_EXPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
557 ofn.lpstrTitle = Caption;
558
559 /* Only set the path if a key (not the root node) is selected */
560 if (hKeyRoot != 0)
561 {
562 ofn.lCustData = (LPARAM) ExportKeyPath;
563 }
564 ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_OVERWRITEPROMPT;
565 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
566 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORTRANGE);
567 if (GetSaveFileName(&ofn))
568 {
569 BOOL result;
570 DWORD format;
571
572 if (ofn.nFilterIndex == 1)
573 format = REG_FORMAT_5;
574 else
575 format = REG_FORMAT_4;
576 result = export_registry_key(ofn.lpstrFile, ExportKeyPath, format);
577 if (!result)
578 {
579 LPSTR p = GetMultiByteString(ofn.lpstrFile);
580 fprintf(stderr, "Can't open file \"%s\"\n", p);
581 HeapFree(GetProcessHeap(), 0, p);
582 return FALSE;
583 }
584 }
585 else
586 {
587 CheckCommDlgError(hWnd);
588 }
589 return TRUE;
590 }
591
592 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
593 {
594 #if 1
595 PRINTDLG pd;
596 UNREFERENCED_PARAMETER(path);
597
598 ZeroMemory(&pd, sizeof(PRINTDLG));
599 pd.lStructSize = sizeof(PRINTDLG);
600 pd.hwndOwner = hWnd;
601 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
602 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
603 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
604 pd.nCopies = 1;
605 pd.nFromPage = 0xFFFF;
606 pd.nToPage = 0xFFFF;
607 pd.nMinPage = 1;
608 pd.nMaxPage = 0xFFFF;
609 if (PrintDlg(&pd))
610 {
611 /* GDI calls to render output. */
612 DeleteDC(pd.hDC); /* Delete DC when done.*/
613 }
614 #else
615 HRESULT hResult;
616 PRINTDLGEX pd;
617
618 hResult = PrintDlgEx(&pd);
619 if (hResult == S_OK)
620 {
621 switch (pd.dwResultAction)
622 {
623 case PD_RESULT_APPLY:
624 /*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. */
625 break;
626 case PD_RESULT_CANCEL:
627 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
628 break;
629 case PD_RESULT_PRINT:
630 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
631 break;
632 default:
633 break;
634 }
635 }
636 else
637 {
638 switch (hResult)
639 {
640 case E_OUTOFMEMORY:
641 /*Insufficient memory. */
642 break;
643 case E_INVALIDARG:
644 /* One or more arguments are invalid. */
645 break;
646 case E_POINTER:
647 /*Invalid pointer. */
648 break;
649 case E_HANDLE:
650 /*Invalid handle. */
651 break;
652 case E_FAIL:
653 /*Unspecified error. */
654 break;
655 default:
656 break;
657 }
658 return FALSE;
659 }
660 #endif
661 return TRUE;
662 }
663
664 static void ChooseFavorite(LPCTSTR pszFavorite)
665 {
666 HKEY hKey = NULL;
667 TCHAR szFavoritePath[512];
668 DWORD cbData, dwType;
669
670 if (RegOpenKeyEx(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
671 goto done;
672
673 cbData = (sizeof(szFavoritePath) / sizeof(szFavoritePath[0])) - 1;
674 memset(szFavoritePath, 0, sizeof(szFavoritePath));
675 if (RegQueryValueEx(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
676 goto done;
677
678 if (dwType == REG_SZ)
679 SelectNode(g_pChildWnd->hTreeWnd, szFavoritePath);
680
681 done:
682 if (hKey)
683 RegCloseKey(hKey);
684 }
685
686 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
687 {
688 BOOL bClipboardOpened = FALSE;
689 BOOL bSuccess = FALSE;
690 TCHAR szBuffer[512];
691 HGLOBAL hGlobal;
692 LPTSTR s;
693
694 if (!OpenClipboard(hWnd))
695 goto done;
696 bClipboardOpened = TRUE;
697
698 if (!EmptyClipboard())
699 goto done;
700
701 if (!GetKeyName(szBuffer, COUNT_OF(szBuffer), hRootKey, keyName))
702 goto done;
703
704 hGlobal = GlobalAlloc(GMEM_MOVEABLE, (lstrlen(szBuffer) + 1) * sizeof(TCHAR));
705 if (!hGlobal)
706 goto done;
707
708 s = GlobalLock(hGlobal);
709 _tcscpy(s, szBuffer);
710 GlobalUnlock(hGlobal);
711
712 #ifdef UNICODE
713 SetClipboardData(CF_UNICODETEXT, hGlobal);
714 #else
715 SetClipboardData(CF_TEXT, hGlobal);
716 #endif
717 bSuccess = TRUE;
718
719 done:
720 if (bClipboardOpened)
721 CloseClipboard();
722 return bSuccess;
723 }
724
725 static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
726 {
727 TCHAR szNewValueFormat[128];
728 TCHAR szNewValue[128];
729 int iIndex = 1;
730 BYTE data[128];
731 DWORD dwExistingType, cbData;
732 LONG lResult;
733 HKEY hKey;
734 LVFINDINFO lvfi;
735
736 if (RegOpenKeyEx(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
737 &hKey) != ERROR_SUCCESS)
738 return FALSE;
739
740 LoadString(hInst, IDS_NEW_VALUE, szNewValueFormat, COUNT_OF(szNewValueFormat));
741
742 do
743 {
744 wsprintf(szNewValue, szNewValueFormat, iIndex++);
745 cbData = sizeof(data);
746 lResult = RegQueryValueEx(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
747 }
748 while(lResult == ERROR_SUCCESS);
749
750 switch(dwType)
751 {
752 case REG_DWORD:
753 cbData = sizeof(DWORD);
754 break;
755 case REG_SZ:
756 case REG_EXPAND_SZ:
757 cbData = sizeof(TCHAR);
758 break;
759 case REG_MULTI_SZ:
760 cbData = sizeof(TCHAR) * 2;
761 break;
762 case REG_QWORD:
763 cbData = sizeof(DWORD) * 2;
764 break;
765 default:
766 cbData = 0;
767 break;
768 }
769 memset(data, 0, cbData);
770 lResult = RegSetValueEx(hKey, szNewValue, 0, dwType, data, cbData);
771 RegCloseKey(hKey);
772 if (lResult != ERROR_SUCCESS)
773 {
774 return FALSE;
775 }
776
777 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
778
779 /* locate the newly added value, and get ready to rename it */
780 memset(&lvfi, 0, sizeof(lvfi));
781 lvfi.flags = LVFI_STRING;
782 lvfi.psz = szNewValue;
783 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
784 if (iIndex >= 0)
785 (void)ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
786
787 return TRUE;
788 }
789
790 static HRESULT
791 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
792 {
793 HRESULT hRet;
794
795 *pDsObjectPicker = NULL;
796
797 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
798 NULL,
799 CLSCTX_INPROC_SERVER,
800 &IID_IDsObjectPicker,
801 (LPVOID*)pDsObjectPicker);
802 if (SUCCEEDED(hRet))
803 {
804 DSOP_INIT_INFO InitInfo;
805 static DSOP_SCOPE_INIT_INFO Scopes[] =
806 {
807 {
808 sizeof(DSOP_SCOPE_INIT_INFO),
809 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
810 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
811 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
812 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
813 0,
814 {
815 {
816 DSOP_FILTER_COMPUTERS,
817 0,
818 0
819 },
820 DSOP_DOWNLEVEL_FILTER_COMPUTERS
821 },
822 NULL,
823 NULL,
824 S_OK
825 },
826 };
827
828 InitInfo.cbSize = sizeof(InitInfo);
829 InitInfo.pwzTargetComputer = NULL;
830 InitInfo.cDsScopeInfos = sizeof(Scopes) / sizeof(Scopes[0]);
831 InitInfo.aDsScopeInfos = Scopes;
832 InitInfo.flOptions = 0;
833 InitInfo.cAttributesToFetch = 0;
834 InitInfo.apwzAttributeNames = NULL;
835
836 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
837 &InitInfo);
838
839 if (FAILED(hRet))
840 {
841 /* delete the object picker in case initialization failed! */
842 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
843 }
844 }
845
846 return hRet;
847 }
848
849 static HRESULT
850 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
851 IN HWND hwndParent OPTIONAL,
852 OUT LPTSTR lpBuffer,
853 IN UINT uSize)
854 {
855 IDataObject *pdo = NULL;
856 HRESULT hRet;
857
858 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
859 hwndParent,
860 &pdo);
861 if (hRet == S_OK)
862 {
863 STGMEDIUM stm;
864 FORMATETC fe;
865
866 fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
867 fe.ptd = NULL;
868 fe.dwAspect = DVASPECT_CONTENT;
869 fe.lindex = -1;
870 fe.tymed = TYMED_HGLOBAL;
871
872 hRet = pdo->lpVtbl->GetData(pdo,
873 &fe,
874 &stm);
875 if (SUCCEEDED(hRet))
876 {
877 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
878 if (SelectionList != NULL)
879 {
880 if (SelectionList->cItems == 1)
881 {
882 size_t nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
883 if (nlen >= uSize)
884 {
885 nlen = uSize - 1;
886 }
887 #if UNICODE
888 memcpy(lpBuffer,
889 SelectionList->aDsSelection[0].pwzName,
890 nlen * sizeof(WCHAR));
891 #else
892 WideCharToMultiByte(CP_ACP,
893 0,
894 SelectionList->aDsSelection[0].pwzName,
895 nlen,
896 lpBuffer,
897 uSize,
898 NULL,
899 NULL);
900 #endif
901 lpBuffer[nlen] = L'\0';
902 }
903
904 GlobalUnlock(stm.hGlobal);
905 }
906
907 ReleaseStgMedium(&stm);
908 }
909
910 pdo->lpVtbl->Release(pdo);
911 }
912
913 return hRet;
914 }
915
916 static VOID
917 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
918 {
919 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
920 }
921
922 /*******************************************************************************
923 *
924 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
925 *
926 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
927 *
928 */
929 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
930 {
931 HKEY hKeyRoot = 0, hKey = 0;
932 LPCTSTR keyPath;
933 LPCTSTR valueName;
934 BOOL result = TRUE;
935 REGSAM regsam = KEY_READ;
936 LONG lRet;
937 int item;
938
939 UNREFERENCED_PARAMETER(lParam);
940 UNREFERENCED_PARAMETER(message);
941
942 switch (LOWORD(wParam))
943 {
944 case ID_REGISTRY_LOADHIVE:
945 LoadHive(hWnd);
946 return TRUE;
947 case ID_REGISTRY_UNLOADHIVE:
948 UnloadHive(hWnd);
949 return TRUE;
950 case ID_REGISTRY_IMPORTREGISTRYFILE:
951 ImportRegistryFile(hWnd);
952 return TRUE;
953 case ID_REGISTRY_EXPORTREGISTRYFILE:
954 ExportRegistryFile(hWnd);
955 return TRUE;
956 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
957 {
958 IDsObjectPicker *ObjectPicker;
959 TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
960 HRESULT hRet;
961
962 hRet = CoInitialize(NULL);
963 if (SUCCEEDED(hRet))
964 {
965 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
966 if (SUCCEEDED(hRet))
967 {
968 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
969 hWnd,
970 szComputerName,
971 sizeof(szComputerName) / sizeof(szComputerName[0]));
972 if (hRet == S_OK)
973 {
974 /* FIXME - connect to the registry */
975 }
976
977 FreeObjectPicker(ObjectPicker);
978 }
979
980 CoUninitialize();
981 }
982
983 return TRUE;
984 }
985 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
986 return TRUE;
987 case ID_REGISTRY_PRINT:
988 PrintRegistryHive(hWnd, _T(""));
989 return TRUE;
990 case ID_REGISTRY_EXIT:
991 DestroyWindow(hWnd);
992 return TRUE;
993 case ID_VIEW_STATUSBAR:
994 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
995 return TRUE;
996 case ID_HELP_HELPTOPICS:
997 WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
998 return TRUE;
999 case ID_HELP_ABOUT:
1000 ShowAboutBox(hWnd);
1001 return TRUE;
1002 case ID_VIEW_SPLIT:
1003 {
1004 RECT rt;
1005 POINT pt, pts;
1006 GetClientRect(g_pChildWnd->hWnd, &rt);
1007 pt.x = rt.left + g_pChildWnd->nSplitPos;
1008 pt.y = (rt.bottom / 2);
1009 pts = pt;
1010 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
1011 {
1012 SetCursorPos(pts.x, pts.y);
1013 SetCursor(LoadCursor(0, IDC_SIZEWE));
1014 SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1015 }
1016 return TRUE;
1017 }
1018 case ID_EDIT_RENAME:
1019 case ID_EDIT_MODIFY:
1020 case ID_EDIT_MODIFY_BIN:
1021 case ID_EDIT_DELETE:
1022 regsam |= KEY_WRITE;
1023 break;
1024 }
1025
1026 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1027 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
1028 if (keyPath)
1029 {
1030 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, regsam, &hKey);
1031 if (lRet != ERROR_SUCCESS) hKey = 0;
1032 }
1033
1034 switch (LOWORD(wParam))
1035 {
1036 case ID_EDIT_MODIFY:
1037 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
1038 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1039 break;
1040 case ID_EDIT_MODIFY_BIN:
1041 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
1042 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1043 break;
1044 case ID_EDIT_RENAME:
1045 if (GetFocus() == g_pChildWnd->hListWnd)
1046 {
1047 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
1048 {
1049 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
1050 if(item > -1)
1051 {
1052 (void)ListView_EditLabel(g_pChildWnd->hListWnd, item);
1053 }
1054 }
1055 }
1056 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1057 {
1058 /* Get focused entry of treeview (if any) */
1059 HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
1060 if (hItem != NULL)
1061 (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, hItem);
1062 }
1063 break;
1064 case ID_EDIT_DELETE:
1065 {
1066 if (GetFocus() == g_pChildWnd->hListWnd)
1067 {
1068 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
1069 if(nSelected >= 1)
1070 {
1071 TCHAR msg[128], caption[128];
1072 LoadString(hInst, IDS_QUERY_DELETE_CONFIRM, caption, sizeof(caption)/sizeof(TCHAR));
1073 LoadString(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, sizeof(msg)/sizeof(TCHAR));
1074 if(MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
1075 {
1076 int ni, errs;
1077
1078 item = -1;
1079 errs = 0;
1080 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
1081 {
1082 valueName = GetValueName(g_pChildWnd->hListWnd, item);
1083 if(RegDeleteValue(hKey, valueName) != ERROR_SUCCESS)
1084 {
1085 errs++;
1086 }
1087 item = ni;
1088 }
1089
1090 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1091 if(errs > 0)
1092 {
1093 LoadString(hInst, IDS_ERR_DELVAL_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
1094 LoadString(hInst, IDS_ERR_DELETEVALUE, msg, sizeof(msg)/sizeof(TCHAR));
1095 MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
1096 }
1097 }
1098 }
1099 }
1100 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1101 {
1102 if (keyPath == 0 || *keyPath == 0)
1103 {
1104 MessageBeep(MB_ICONHAND);
1105 }
1106 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1107 {
1108 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1109 RefreshTreeView(g_pChildWnd->hTreeWnd);
1110 }
1111 }
1112 break;
1113 }
1114 case ID_EDIT_NEW_STRINGVALUE:
1115 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
1116 break;
1117 case ID_EDIT_NEW_BINARYVALUE:
1118 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
1119 break;
1120 case ID_EDIT_NEW_DWORDVALUE:
1121 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
1122 break;
1123 case ID_EDIT_NEW_MULTISTRINGVALUE:
1124 CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
1125 break;
1126 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
1127 CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
1128 break;
1129 case ID_EDIT_FIND:
1130 FindDialog(hWnd);
1131 break;
1132 case ID_EDIT_FINDNEXT:
1133 FindNext(hWnd);
1134 break;
1135 case ID_EDIT_COPYKEYNAME:
1136 CopyKeyName(hWnd, hKeyRoot, keyPath);
1137 break;
1138 case ID_EDIT_PERMISSIONS:
1139 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1140 break;
1141 case ID_REGISTRY_PRINTERSETUP:
1142 /*PRINTDLG pd;*/
1143 /*PrintDlg(&pd);*/
1144 /*PAGESETUPDLG psd;*/
1145 /*PageSetupDlg(&psd);*/
1146 break;
1147 case ID_REGISTRY_OPENLOCAL:
1148 break;
1149
1150 case ID_VIEW_REFRESH:
1151 RefreshTreeView(g_pChildWnd->hTreeWnd);
1152 /*RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL); */
1153 break;
1154 /*case ID_OPTIONS_TOOLBAR:*/
1155 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1156 /* break;*/
1157 case ID_EDIT_NEW_KEY:
1158 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1159 break;
1160 default:
1161 if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
1162 {
1163 HMENU hMenu;
1164 MENUITEMINFO mii;
1165 TCHAR szFavorite[512];
1166
1167 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
1168
1169 memset(&mii, 0, sizeof(mii));
1170 mii.cbSize = sizeof(mii);
1171 mii.fMask = MIIM_TYPE;
1172 mii.fType = MFT_STRING;
1173 mii.dwTypeData = szFavorite;
1174 mii.cch = sizeof(szFavorite) / sizeof(szFavorite[0]);
1175
1176 if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
1177 {
1178 ChooseFavorite(szFavorite);
1179 }
1180 }
1181 else
1182 {
1183 result = FALSE;
1184 }
1185 break;
1186 }
1187
1188 if(hKey)
1189 RegCloseKey(hKey);
1190 return result;
1191 }
1192
1193 /********************************************************************************
1194 *
1195 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1196 *
1197 * PURPOSE: Processes messages for the main frame window.
1198 *
1199 * WM_COMMAND - process the application menu
1200 * WM_DESTROY - post a quit message and return
1201 *
1202 */
1203
1204 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1205 {
1206 switch (message)
1207 {
1208 case WM_CREATE:
1209 CreateWindowEx(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
1210 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1211 hWnd, (HMENU)0, hInst, 0);
1212 break;
1213 case WM_COMMAND:
1214 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1215 return DefWindowProc(hWnd, message, wParam, lParam);
1216 break;
1217 case WM_ACTIVATE:
1218 if (LOWORD(hWnd))
1219 SetFocus(g_pChildWnd->hWnd);
1220 break;
1221 case WM_SIZE:
1222 resize_frame_client(hWnd);
1223 break;
1224 case WM_TIMER:
1225 break;
1226 case WM_INITMENU:
1227 OnInitMenu(hWnd);
1228 break;
1229 case WM_ENTERMENULOOP:
1230 OnEnterMenuLoop(hWnd);
1231 break;
1232 case WM_EXITMENULOOP:
1233 OnExitMenuLoop(hWnd);
1234 break;
1235 case WM_MENUSELECT:
1236 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1237 break;
1238 case WM_SYSCOLORCHANGE:
1239 /* Forward WM_SYSCOLORCHANGE to common controls */
1240 SendMessage(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
1241 SendMessage(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
1242 break;
1243 case WM_DESTROY:
1244 WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
1245 SaveSettings();
1246 PostQuitMessage(0);
1247 default:
1248 return DefWindowProc(hWnd, message, wParam, lParam);
1249 }
1250 return 0;
1251 }