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