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