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