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