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