d11c8a01e14fcaff75a790c9dbc67417115898a0
[reactos.git] / base / applications / regedit / framewnd.c
1 /*
2 * Regedit frame window
3 *
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <regedit.h>
22
23 /********************************************************************************
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 SetupStatusBar(hWnd, TRUE);
50 GetClientRect(hStatusBar, &rt);
51 prect->bottom -= rt.bottom;
52 }
53 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
54 }
55
56 static void resize_frame_client(HWND hWnd)
57 {
58 RECT rect;
59
60 GetClientRect(hWnd, &rect);
61 resize_frame_rect(hWnd, &rect);
62 }
63
64 /********************************************************************************/
65
66 static void OnInitMenu(HWND hWnd)
67 {
68 LONG lResult;
69 HKEY hKey = NULL;
70 DWORD dwIndex, cbValueName, cbValueData, dwType;
71 TCHAR szValueName[256];
72 BYTE abValueData[256];
73 static int s_nFavoriteMenuSubPos = -1;
74 HMENU hMenu;
75 BOOL bDisplayedAny = FALSE;
76
77 /* Find Favorites menu and clear it out */
78 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
79 if (!hMenu)
80 goto done;
81 if (s_nFavoriteMenuSubPos < 0)
82 {
83 s_nFavoriteMenuSubPos = GetMenuItemCount(hMenu);
84 }
85 else
86 {
87 while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION))
88 ;
89 }
90
91 lResult = RegOpenKey(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
92 if (lResult != ERROR_SUCCESS)
93 goto done;
94
95 dwIndex = 0;
96 do
97 {
98 cbValueName = COUNT_OF(szValueName);
99 cbValueData = sizeof(abValueData);
100 lResult = RegEnumValue(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
101 if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
102 {
103 if (!bDisplayedAny)
104 {
105 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
106 bDisplayedAny = TRUE;
107 }
108 AppendMenu(hMenu, 0, ID_FAVORITES_MIN + GetMenuItemCount(hMenu), szValueName);
109 }
110 dwIndex++;
111 }
112 while(lResult == ERROR_SUCCESS);
113
114 done:
115 if (hKey)
116 RegCloseKey(hKey);
117 }
118
119 static void OnEnterMenuLoop(HWND hWnd)
120 {
121 int nParts;
122 UNREFERENCED_PARAMETER(hWnd);
123
124 /* Update the status bar pane sizes */
125 nParts = -1;
126 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
127 bInMenuLoop = TRUE;
128 SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
129 }
130
131 static void OnExitMenuLoop(HWND hWnd)
132 {
133 bInMenuLoop = FALSE;
134 /* Update the status bar pane sizes*/
135 SetupStatusBar(hWnd, TRUE);
136 UpdateStatusBar();
137 }
138
139 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
140 {
141 TCHAR str[100];
142
143 _tcscpy(str, _T(""));
144 if (nFlags & MF_POPUP) {
145 if (hSysMenu != GetMenu(hWnd)) {
146 if (nItemID == 2) nItemID = 5;
147 }
148 }
149 if (LoadString(hInst, nItemID, str, 100)) {
150 /* load appropriate string*/
151 LPTSTR lpsz = str;
152 /* first newline terminates actual string*/
153 lpsz = _tcschr(lpsz, _T('\n'));
154 if (lpsz != NULL)
155 *lpsz = '\0';
156 }
157 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
158 }
159
160 void SetupStatusBar(HWND hWnd, BOOL bResize)
161 {
162 RECT rc;
163 int nParts;
164 GetClientRect(hWnd, &rc);
165 nParts = rc.right;
166 /* nParts = -1;*/
167 if (bResize)
168 SendMessage(hStatusBar, WM_SIZE, 0, 0);
169 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
170 }
171
172 void UpdateStatusBar(void)
173 {
174 NMHDR nmhdr;
175 ZeroMemory(&nmhdr, sizeof(NMHDR));
176 nmhdr.code = TVN_SELCHANGED;
177 SendMessage(g_pChildWnd->hWnd, WM_NOTIFY, (WPARAM)TREE_WINDOW, (LPARAM)&nmhdr);
178 }
179
180 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
181 {
182 BOOL vis = IsWindowVisible(hchild);
183 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
184
185 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
186 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
187 resize_frame_client(hWnd);
188 }
189
190 static BOOL CheckCommDlgError(HWND hWnd)
191 {
192 DWORD dwErrorCode = CommDlgExtendedError();
193 UNREFERENCED_PARAMETER(hWnd);
194 switch (dwErrorCode) {
195 case CDERR_DIALOGFAILURE:
196 break;
197 case CDERR_FINDRESFAILURE:
198 break;
199 case CDERR_NOHINSTANCE:
200 break;
201 case CDERR_INITIALIZATION:
202 break;
203 case CDERR_NOHOOK:
204 break;
205 case CDERR_LOCKRESFAILURE:
206 break;
207 case CDERR_NOTEMPLATE:
208 break;
209 case CDERR_LOADRESFAILURE:
210 break;
211 case CDERR_STRUCTSIZE:
212 break;
213 case CDERR_LOADSTRFAILURE:
214 break;
215 case FNERR_BUFFERTOOSMALL:
216 break;
217 case CDERR_MEMALLOCFAILURE:
218 break;
219 case FNERR_INVALIDFILENAME:
220 break;
221 case CDERR_MEMLOCKFAILURE:
222 break;
223 case FNERR_SUBCLASSFAILURE:
224 break;
225 default:
226 break;
227 }
228 return TRUE;
229 }
230
231 TCHAR FileNameBuffer[_MAX_PATH];
232 TCHAR FileTitleBuffer[_MAX_PATH];
233
234 typedef struct
235 {
236 UINT DisplayID;
237 UINT FilterID;
238 } FILTERPAIR, *PFILTERPAIR;
239
240 void
241 BuildFilterStrings(TCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
242 {
243 int i, c;
244
245 c = 0;
246 for(i = 0; i < PairCount; i++)
247 {
248 c += LoadString(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(TCHAR));
249 Filter[++c] = '\0';
250 c += LoadString(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(TCHAR));
251 Filter[++c] = '\0';
252 }
253 Filter[++c] = '\0';
254 }
255
256 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
257 {
258 FILTERPAIR FilterPairs[3];
259 static TCHAR Filter[1024];
260
261 memset(pofn, 0, sizeof(OPENFILENAME));
262 pofn->lStructSize = sizeof(OPENFILENAME);
263 pofn->hwndOwner = hWnd;
264 pofn->hInstance = hInst;
265
266 /* create filter string */
267 FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
268 FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
269 FilterPairs[1].DisplayID = IDS_FLT_REGEDIT4;
270 FilterPairs[1].FilterID = IDS_FLT_REGEDIT4_FLT;
271 FilterPairs[2].DisplayID = IDS_FLT_ALLFILES;
272 FilterPairs[2].FilterID = IDS_FLT_ALLFILES_FLT;
273 BuildFilterStrings(Filter, FilterPairs, sizeof(FilterPairs) / sizeof(FILTERPAIR));
274
275 pofn->lpstrFilter = Filter;
276 pofn->lpstrFile = FileNameBuffer;
277 pofn->nMaxFile = _MAX_PATH;
278 pofn->lpstrFileTitle = FileTitleBuffer;
279 pofn->nMaxFileTitle = _MAX_PATH;
280 pofn->Flags = OFN_HIDEREADONLY;
281 pofn->lpstrDefExt = TEXT("reg");
282 return TRUE;
283 }
284
285 static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
286 {
287 static LPTSTR sKey = NULL;
288 static INT sLength = 0;
289 switch(uMsg)
290 {
291 case WM_INITDIALOG:
292 sKey = (LPTSTR)lParam;
293 sLength = 128; /* FIXME: Ugly hack! */
294 case WM_COMMAND:
295 switch(LOWORD(wParam))
296 {
297 case IDOK:
298 if(GetDlgItemText(hWndDlg, IDC_EDIT_KEY, sKey, sLength))
299 return EndDialog(hWndDlg, -1);
300 else
301 return EndDialog(hWndDlg, 0);
302 case IDCANCEL:
303 return EndDialog(hWndDlg, 0);
304 }
305 break;
306 }
307 return FALSE;
308 }
309
310 static BOOL LoadHive(HWND hWnd)
311 {
312 OPENFILENAME ofn;
313 TCHAR Caption[128];
314 LPCTSTR pszKeyPath;
315 TCHAR xPath[128];
316 HKEY hRootKey;
317 TCHAR Filter[1024];
318 FILTERPAIR filter;
319 /* get the item key to load the hive in */
320 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
321 /* initialize the "open file" dialog */
322 InitOpenFileName(hWnd, &ofn);
323 /* build the "All Files" filter up */
324 filter.DisplayID = IDS_FLT_ALLFILES;
325 filter.FilterID = IDS_FLT_ALLFILES_FLT;
326 BuildFilterStrings(Filter, &filter, sizeof(filter));
327 ofn.lpstrFilter = Filter;
328 /* load and set the caption and flags for dialog */
329 LoadString(hInst, IDS_LOAD_HIVE, Caption, COUNT_OF(Caption));
330 ofn.lpstrTitle = Caption;
331 ofn.Flags |= OFN_ENABLESIZING;
332 /* ofn.lCustData = ;*/
333 /* now load the hive */
334 if (GetOpenFileName(&ofn))
335 {
336 if(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOADHIVE), hWnd, &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
337 {
338 LONG regLoadResult = RegLoadKey(hRootKey, xPath, ofn.lpstrFile);
339 if(regLoadResult == ERROR_SUCCESS)
340 {
341 /* refresh tree and list views */
342 RefreshTreeView(g_pChildWnd->hTreeWnd);
343 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
344 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
345 }
346 else
347 {
348 ErrorMessageBox(hWnd, Caption, regLoadResult);
349 return FALSE;
350 }
351 }
352 } else {
353 CheckCommDlgError(hWnd);
354 }
355 return TRUE;
356 }
357
358 static BOOL UnloadHive(HWND hWnd)
359 {
360 TCHAR Caption[128];
361 LPCTSTR pszKeyPath;
362 HKEY hRootKey;
363 LONG regUnloadResult;
364
365 /* get the item key to unload */
366 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
367 /* load and set the caption and flags for dialog */
368 LoadString(hInst, IDS_UNLOAD_HIVE, Caption, COUNT_OF(Caption));
369 /* now unload the hive */
370 regUnloadResult = RegUnLoadKey(hRootKey, pszKeyPath);
371 if(regUnloadResult == ERROR_SUCCESS)
372 {
373 /* refresh tree and list views */
374 RefreshTreeView(g_pChildWnd->hTreeWnd);
375 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
376 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
377 }
378 else
379 {
380 ErrorMessageBox(hWnd, Caption, regUnloadResult);
381 return FALSE;
382 }
383 return TRUE;
384 }
385
386 static BOOL ImportRegistryFile(HWND hWnd)
387 {
388 OPENFILENAME ofn;
389 TCHAR Caption[128];
390 LPCTSTR pszKeyPath;
391 HKEY hRootKey;
392
393 InitOpenFileName(hWnd, &ofn);
394 LoadString(hInst, IDS_IMPORT_REG_FILE, Caption, COUNT_OF(Caption));
395 ofn.lpstrTitle = Caption;
396 ofn.Flags |= OFN_ENABLESIZING;
397 /* ofn.lCustData = ;*/
398 if (GetOpenFileName(&ofn)) {
399 FILE *fp = _wfopen(ofn.lpstrFile, L"r");
400 if (fp == NULL || !import_registry_file(fp)) {
401 LPSTR p = GetMultiByteString(ofn.lpstrFile);
402 fprintf(stderr, "Can't open file \"%s\"\n", p);
403 HeapFree(GetProcessHeap(), 0, p);
404 if (fp != NULL)
405 fclose(fp);
406 return FALSE;
407 }
408 fclose(fp);
409 } else {
410 CheckCommDlgError(hWnd);
411 }
412
413 RefreshTreeView(g_pChildWnd->hTreeWnd);
414 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
415 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
416
417 return TRUE;
418 }
419
420 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
421 {
422 HWND hwndExportAll;
423 HWND hwndExportBranch;
424 HWND hwndExportBranchText;
425 UINT_PTR iResult = 0;
426 OPENFILENAME *pOfn;
427 LPTSTR pszSelectedKey;
428 OFNOTIFY *pOfnNotify;
429
430 UNREFERENCED_PARAMETER(wParam);
431
432 switch(uiMsg) {
433 case WM_INITDIALOG:
434 pOfn = (OPENFILENAME *) lParam;
435 pszSelectedKey = (LPTSTR) pOfn->lCustData;
436
437 hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
438 if (hwndExportAll)
439 SendMessage(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
440
441 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
442 if (hwndExportBranch)
443 SendMessage(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
444
445 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
446 if (hwndExportBranchText)
447 SetWindowText(hwndExportBranchText, pszSelectedKey);
448 break;
449
450 case WM_NOTIFY:
451 if (((NMHDR *) lParam)->code == CDN_FILEOK)
452 {
453 pOfnNotify = (OFNOTIFY *) lParam;
454 pszSelectedKey = (LPTSTR) pOfnNotify->lpOFN->lCustData;
455
456 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
457 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
458 if (hwndExportBranch && hwndExportBranchText
459 && (SendMessage(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
460 {
461 GetWindowText(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
462 }
463 else
464 {
465 pszSelectedKey[0] = '\0';
466 }
467 }
468 break;
469 }
470 return iResult;
471 }
472
473 BOOL ExportRegistryFile(HWND hWnd)
474 {
475 OPENFILENAME ofn;
476 TCHAR ExportKeyPath[_MAX_PATH];
477 TCHAR Caption[128];
478 HKEY hKeyRoot;
479 LPCTSTR pszKeyPath;
480
481 /* Figure out which key path we are exporting */
482 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
483 GetKeyName(ExportKeyPath, COUNT_OF(ExportKeyPath), hKeyRoot, pszKeyPath);
484
485 InitOpenFileName(hWnd, &ofn);
486 LoadString(hInst, IDS_EXPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
487 ofn.lpstrTitle = Caption;
488
489 /* Only set the path if a key (not the root node) is selected */
490 if (hKeyRoot != 0)
491 {
492 ofn.lCustData = (LPARAM) ExportKeyPath;
493 }
494 ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_OVERWRITEPROMPT;
495 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
496 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORTRANGE);
497 if (GetSaveFileName(&ofn)) {
498 BOOL result;
499 DWORD format;
500
501 if (ofn.nFilterIndex == 1)
502 format = REG_FORMAT_5;
503 else
504 format = REG_FORMAT_4;
505 result = export_registry_key(ofn.lpstrFile, ExportKeyPath, format);
506 if (!result) {
507 LPSTR p = GetMultiByteString(ofn.lpstrFile);
508 fprintf(stderr, "Can't open file \"%s\"\n", p);
509 HeapFree(GetProcessHeap(), 0, p);
510 return FALSE;
511 }
512 } else {
513 CheckCommDlgError(hWnd);
514 }
515 return TRUE;
516 }
517
518 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
519 {
520 #if 1
521 PRINTDLG pd;
522 UNREFERENCED_PARAMETER(path);
523
524 ZeroMemory(&pd, sizeof(PRINTDLG));
525 pd.lStructSize = sizeof(PRINTDLG);
526 pd.hwndOwner = hWnd;
527 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
528 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
529 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
530 pd.nCopies = 1;
531 pd.nFromPage = 0xFFFF;
532 pd.nToPage = 0xFFFF;
533 pd.nMinPage = 1;
534 pd.nMaxPage = 0xFFFF;
535 if (PrintDlg(&pd)) {
536 /* GDI calls to render output. */
537 DeleteDC(pd.hDC); /* Delete DC when done.*/
538 }
539 #else
540 HRESULT hResult;
541 PRINTDLGEX pd;
542
543 hResult = PrintDlgEx(&pd);
544 if (hResult == S_OK) {
545 switch (pd.dwResultAction) {
546 case PD_RESULT_APPLY:
547 /*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. */
548 break;
549 case PD_RESULT_CANCEL:
550 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
551 break;
552 case PD_RESULT_PRINT:
553 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
554 break;
555 default:
556 break;
557 }
558 } else {
559 switch (hResult) {
560 case E_OUTOFMEMORY:
561 /*Insufficient memory. */
562 break;
563 case E_INVALIDARG:
564 /* One or more arguments are invalid. */
565 break;
566 case E_POINTER:
567 /*Invalid pointer. */
568 break;
569 case E_HANDLE:
570 /*Invalid handle. */
571 break;
572 case E_FAIL:
573 /*Unspecified error. */
574 break;
575 default:
576 break;
577 }
578 return FALSE;
579 }
580 #endif
581 return TRUE;
582 }
583
584 static void ChooseFavorite(LPCTSTR pszFavorite)
585 {
586 HKEY hKey = NULL;
587 TCHAR szFavoritePath[512];
588 DWORD cbData, dwType;
589
590 if (RegOpenKeyEx(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
591 goto done;
592
593 cbData = (sizeof(szFavoritePath) / sizeof(szFavoritePath[0])) - 1;
594 memset(szFavoritePath, 0, sizeof(szFavoritePath));
595 if (RegQueryValueEx(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
596 goto done;
597
598 if (dwType == REG_SZ)
599 SelectNode(g_pChildWnd->hTreeWnd, szFavoritePath);
600
601 done:
602 if (hKey)
603 RegCloseKey(hKey);
604 }
605
606 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
607 {
608 BOOL bClipboardOpened = FALSE;
609 BOOL bSuccess = FALSE;
610 TCHAR szBuffer[512];
611 HGLOBAL hGlobal;
612 LPTSTR s;
613
614 if (!OpenClipboard(hWnd))
615 goto done;
616 bClipboardOpened = TRUE;
617
618 if (!EmptyClipboard())
619 goto done;
620
621 if (!GetKeyName(szBuffer, COUNT_OF(szBuffer), hRootKey, keyName))
622 goto done;
623
624 hGlobal = GlobalAlloc(GMEM_MOVEABLE, (lstrlen(szBuffer) + 1) * sizeof(TCHAR));
625 if (!hGlobal)
626 goto done;
627
628 s = GlobalLock(hGlobal);
629 _tcscpy(s, szBuffer);
630 GlobalUnlock(hGlobal);
631
632 #ifdef UNICODE
633 SetClipboardData(CF_UNICODETEXT, hGlobal);
634 #else
635 SetClipboardData(CF_TEXT, hGlobal);
636 #endif
637 bSuccess = TRUE;
638
639 done:
640 if (bClipboardOpened)
641 CloseClipboard();
642 return bSuccess;
643 }
644
645 static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
646 {
647 TCHAR szNewValueFormat[128];
648 TCHAR szNewValue[128];
649 int iIndex = 1;
650 BYTE data[128];
651 DWORD dwExistingType, cbData;
652 LONG lResult;
653 HKEY hKey;
654 LVFINDINFO lvfi;
655
656 if (RegOpenKeyEx(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
657 &hKey) != ERROR_SUCCESS)
658 return FALSE;
659
660 LoadString(hInst, IDS_NEW_VALUE, szNewValueFormat, COUNT_OF(szNewValueFormat));
661
662 do
663 {
664 wsprintf(szNewValue, szNewValueFormat, iIndex++);
665 cbData = sizeof(data);
666 lResult = RegQueryValueEx(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
667 } while(lResult == ERROR_SUCCESS);
668
669 switch(dwType) {
670 case REG_DWORD:
671 cbData = sizeof(DWORD);
672 break;
673 case REG_SZ:
674 case REG_EXPAND_SZ:
675 cbData = sizeof(TCHAR);
676 break;
677 case REG_MULTI_SZ:
678 cbData = sizeof(TCHAR) * 2;
679 break;
680 case REG_QWORD:
681 cbData = sizeof(DWORD) * 2;
682 break;
683 default:
684 cbData = 0;
685 break;
686 }
687 memset(data, 0, cbData);
688 lResult = RegSetValueEx(hKey, szNewValue, 0, dwType, data, cbData);
689 RegCloseKey(hKey);
690 if (lResult != ERROR_SUCCESS)
691 {
692 return FALSE;
693 }
694
695 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
696
697 /* locate the newly added value, and get ready to rename it */
698 memset(&lvfi, 0, sizeof(lvfi));
699 lvfi.flags = LVFI_STRING;
700 lvfi.psz = szNewValue;
701 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
702 if (iIndex >= 0)
703 (void)ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
704
705 return TRUE;
706 }
707
708 static HRESULT
709 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
710 {
711 HRESULT hRet;
712
713 *pDsObjectPicker = NULL;
714
715 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
716 NULL,
717 CLSCTX_INPROC_SERVER,
718 &IID_IDsObjectPicker,
719 (LPVOID*)pDsObjectPicker);
720 if (SUCCEEDED(hRet))
721 {
722 DSOP_INIT_INFO InitInfo;
723 static DSOP_SCOPE_INIT_INFO Scopes[] =
724 {
725 {
726 sizeof(DSOP_SCOPE_INIT_INFO),
727 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
728 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
729 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
730 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
731 0,
732 {
733 {
734 DSOP_FILTER_COMPUTERS,
735 0,
736 0
737 },
738 DSOP_DOWNLEVEL_FILTER_COMPUTERS
739 },
740 NULL,
741 NULL,
742 S_OK
743 },
744 };
745
746 InitInfo.cbSize = sizeof(InitInfo);
747 InitInfo.pwzTargetComputer = NULL;
748 InitInfo.cDsScopeInfos = sizeof(Scopes) / sizeof(Scopes[0]);
749 InitInfo.aDsScopeInfos = Scopes;
750 InitInfo.flOptions = 0;
751 InitInfo.cAttributesToFetch = 0;
752 InitInfo.apwzAttributeNames = NULL;
753
754 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
755 &InitInfo);
756
757 if (FAILED(hRet))
758 {
759 /* delete the object picker in case initialization failed! */
760 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
761 }
762 }
763
764 return hRet;
765 }
766
767 static HRESULT
768 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
769 IN HWND hwndParent OPTIONAL,
770 OUT LPTSTR lpBuffer,
771 IN UINT uSize)
772 {
773 IDataObject *pdo = NULL;
774 HRESULT hRet;
775
776 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
777 hwndParent,
778 &pdo);
779 if (hRet == S_OK)
780 {
781 STGMEDIUM stm;
782 FORMATETC fe;
783
784 fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
785 fe.ptd = NULL;
786 fe.dwAspect = DVASPECT_CONTENT;
787 fe.lindex = -1;
788 fe.tymed = TYMED_HGLOBAL;
789
790 hRet = pdo->lpVtbl->GetData(pdo,
791 &fe,
792 &stm);
793 if (SUCCEEDED(hRet))
794 {
795 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
796 if (SelectionList != NULL)
797 {
798 if (SelectionList->cItems == 1)
799 {
800 size_t nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
801 if (nlen >= uSize)
802 {
803 nlen = uSize - 1;
804 }
805 #if UNICODE
806 memcpy(lpBuffer,
807 SelectionList->aDsSelection[0].pwzName,
808 nlen * sizeof(WCHAR));
809 #else
810 WideCharToMultiByte(CP_ACP,
811 0,
812 SelectionList->aDsSelection[0].pwzName,
813 nlen,
814 lpBuffer,
815 uSize,
816 NULL,
817 NULL);
818 #endif
819 lpBuffer[nlen] = L'\0';
820 }
821
822 GlobalUnlock(stm.hGlobal);
823 }
824
825 ReleaseStgMedium(&stm);
826 }
827
828 pdo->lpVtbl->Release(pdo);
829 }
830
831 return hRet;
832 }
833
834 static VOID
835 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
836 {
837 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
838 }
839
840 /*******************************************************************************
841 *
842 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
843 *
844 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
845 *
846 */
847 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
848 {
849 HKEY hKeyRoot = 0, hKey = 0;
850 LPCTSTR keyPath;
851 LPCTSTR valueName;
852 BOOL result = TRUE;
853 REGSAM regsam = KEY_READ;
854 LONG lRet;
855 int item;
856
857 UNREFERENCED_PARAMETER(lParam);
858 UNREFERENCED_PARAMETER(message);
859
860 switch (LOWORD(wParam)) {
861 case ID_REGISTRY_LOADHIVE:
862 LoadHive(hWnd);
863 return TRUE;
864 case ID_REGISTRY_UNLOADHIVE:
865 UnloadHive(hWnd);
866 return TRUE;
867 case ID_REGISTRY_IMPORTREGISTRYFILE:
868 ImportRegistryFile(hWnd);
869 return TRUE;
870 case ID_REGISTRY_EXPORTREGISTRYFILE:
871 ExportRegistryFile(hWnd);
872 return TRUE;
873 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
874 {
875 IDsObjectPicker *ObjectPicker;
876 TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
877 HRESULT hRet;
878
879 hRet = CoInitialize(NULL);
880 if (SUCCEEDED(hRet))
881 {
882 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
883 if (SUCCEEDED(hRet))
884 {
885 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
886 hWnd,
887 szComputerName,
888 sizeof(szComputerName) / sizeof(szComputerName[0]));
889 if (hRet == S_OK)
890 {
891 /* FIXME - connect to the registry */
892 }
893
894 FreeObjectPicker(ObjectPicker);
895 }
896
897 CoUninitialize();
898 }
899
900 return TRUE;
901 }
902 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
903 return TRUE;
904 case ID_REGISTRY_PRINT:
905 PrintRegistryHive(hWnd, _T(""));
906 return TRUE;
907 case ID_REGISTRY_EXIT:
908 DestroyWindow(hWnd);
909 return TRUE;
910 case ID_VIEW_STATUSBAR:
911 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
912 return TRUE;
913 case ID_HELP_HELPTOPICS:
914 WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
915 return TRUE;
916 case ID_HELP_ABOUT:
917 ShowAboutBox(hWnd);
918 return TRUE;
919 case ID_VIEW_SPLIT:
920 {
921 RECT rt;
922 POINT pt, pts;
923 GetClientRect(g_pChildWnd->hWnd, &rt);
924 pt.x = rt.left + g_pChildWnd->nSplitPos;
925 pt.y = (rt.bottom / 2);
926 pts = pt;
927 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
928 {
929 SetCursorPos(pts.x, pts.y);
930 SetCursor(LoadCursor(0, IDC_SIZEWE));
931 SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
932 }
933 return TRUE;
934 }
935 case ID_EDIT_RENAME:
936 case ID_EDIT_MODIFY:
937 case ID_EDIT_MODIFY_BIN:
938 case ID_EDIT_DELETE:
939 regsam |= KEY_WRITE;
940 break;
941 }
942
943 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
944 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
945 if (keyPath) {
946 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, regsam, &hKey);
947 if (lRet != ERROR_SUCCESS) hKey = 0;
948 }
949
950 switch (LOWORD(wParam)) {
951 case ID_EDIT_MODIFY:
952 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
953 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
954 break;
955 case ID_EDIT_MODIFY_BIN:
956 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
957 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
958 break;
959 case ID_EDIT_RENAME:
960 if (GetFocus() == g_pChildWnd->hListWnd)
961 {
962 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
963 {
964 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
965 if(item > -1)
966 {
967 (void)ListView_EditLabel(g_pChildWnd->hListWnd, item);
968 }
969 }
970 }
971 else if (GetFocus() == g_pChildWnd->hTreeWnd)
972 {
973 /* Get focused entry of treeview (if any) */
974 HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
975 if (hItem != NULL)
976 (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, hItem);
977 }
978 break;
979 case ID_EDIT_DELETE:
980 {
981 if (GetFocus() == g_pChildWnd->hListWnd)
982 {
983 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
984 if(nSelected >= 1)
985 {
986 TCHAR msg[128], caption[128];
987 LoadString(hInst, IDS_QUERY_DELETE_CONFIRM, caption, sizeof(caption)/sizeof(TCHAR));
988 LoadString(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, sizeof(msg)/sizeof(TCHAR));
989 if(MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
990 {
991 int ni, errs;
992
993 item = -1;
994 errs = 0;
995 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
996 {
997 valueName = GetValueName(g_pChildWnd->hListWnd, item);
998 if(RegDeleteValue(hKey, valueName) != ERROR_SUCCESS)
999 {
1000 errs++;
1001 }
1002 item = ni;
1003 }
1004
1005 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
1006 if(errs > 0)
1007 {
1008 LoadString(hInst, IDS_ERR_DELVAL_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
1009 LoadString(hInst, IDS_ERR_DELETEVALUE, msg, sizeof(msg)/sizeof(TCHAR));
1010 MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
1011 }
1012 }
1013 }
1014 }
1015 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1016 {
1017 if (keyPath == 0 || *keyPath == 0)
1018 {
1019 MessageBeep(MB_ICONHAND);
1020 } else
1021 if (DeleteKey(hWnd, hKeyRoot, keyPath))
1022 {
1023 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1024 RefreshTreeView(g_pChildWnd->hTreeWnd);
1025 }
1026 }
1027 break;
1028 }
1029 case ID_EDIT_NEW_STRINGVALUE:
1030 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
1031 break;
1032 case ID_EDIT_NEW_BINARYVALUE:
1033 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
1034 break;
1035 case ID_EDIT_NEW_DWORDVALUE:
1036 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
1037 break;
1038 case ID_EDIT_NEW_MULTISTRINGVALUE:
1039 CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
1040 break;
1041 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
1042 CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
1043 break;
1044 case ID_EDIT_FIND:
1045 FindDialog(hWnd);
1046 break;
1047 case ID_EDIT_FINDNEXT:
1048 FindNext(hWnd);
1049 break;
1050 case ID_EDIT_COPYKEYNAME:
1051 CopyKeyName(hWnd, hKeyRoot, keyPath);
1052 break;
1053 case ID_EDIT_PERMISSIONS:
1054 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1055 break;
1056 case ID_REGISTRY_PRINTERSETUP:
1057 /*PRINTDLG pd;*/
1058 /*PrintDlg(&pd);*/
1059 /*PAGESETUPDLG psd;*/
1060 /*PageSetupDlg(&psd);*/
1061 break;
1062 case ID_REGISTRY_OPENLOCAL:
1063 break;
1064
1065 case ID_VIEW_REFRESH:
1066 RefreshTreeView(g_pChildWnd->hTreeWnd);
1067 /*RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL); */
1068 break;
1069 /*case ID_OPTIONS_TOOLBAR:*/
1070 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1071 /* break;*/
1072 case ID_EDIT_NEW_KEY:
1073 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1074 break;
1075 default:
1076 if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
1077 {
1078 HMENU hMenu;
1079 MENUITEMINFO mii;
1080 TCHAR szFavorite[512];
1081
1082 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
1083
1084 memset(&mii, 0, sizeof(mii));
1085 mii.cbSize = sizeof(mii);
1086 mii.fMask = MIIM_TYPE;
1087 mii.fType = MFT_STRING;
1088 mii.dwTypeData = szFavorite;
1089 mii.cch = sizeof(szFavorite) / sizeof(szFavorite[0]);
1090
1091 if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
1092 {
1093 ChooseFavorite(szFavorite);
1094 }
1095 }
1096 else
1097 {
1098 result = FALSE;
1099 }
1100 break;
1101 }
1102
1103 if(hKey)
1104 RegCloseKey(hKey);
1105 return result;
1106 }
1107
1108 /********************************************************************************
1109 *
1110 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1111 *
1112 * PURPOSE: Processes messages for the main frame window.
1113 *
1114 * WM_COMMAND - process the application menu
1115 * WM_DESTROY - post a quit message and return
1116 *
1117 */
1118
1119 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1120 {
1121 switch (message) {
1122 case WM_CREATE:
1123 CreateWindowEx(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
1124 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1125 hWnd, (HMENU)0, hInst, 0);
1126 break;
1127 case WM_COMMAND:
1128 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1129 return DefWindowProc(hWnd, message, wParam, lParam);
1130 break;
1131 case WM_ACTIVATE:
1132 if (LOWORD(hWnd))
1133 SetFocus(g_pChildWnd->hWnd);
1134 break;
1135 case WM_SIZE:
1136 resize_frame_client(hWnd);
1137 break;
1138 case WM_TIMER:
1139 break;
1140 case WM_INITMENU:
1141 OnInitMenu(hWnd);
1142 break;
1143 case WM_ENTERMENULOOP:
1144 OnEnterMenuLoop(hWnd);
1145 break;
1146 case WM_EXITMENULOOP:
1147 OnExitMenuLoop(hWnd);
1148 break;
1149 case WM_MENUSELECT:
1150 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1151 break;
1152 case WM_DESTROY:
1153 WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
1154 PostQuitMessage(0);
1155 default:
1156 return DefWindowProc(hWnd, message, wParam, lParam);
1157 }
1158 return 0;
1159 }