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