983d598fc0f1374b0460fdf20b1ef84932053edb
[reactos.git] / reactos / subsys / system / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <windows.h>
22 #include <tchar.h>
23 #include <commctrl.h>
24 #include <commdlg.h>
25 #include <cderr.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <shellapi.h>
29 #include <objsel.h>
30 #include <objbase.h>
31 #include <ole2.h>
32
33 #include "main.h"
34 #include "regproc.h"
35
36 /********************************************************************************
37 * Global and Local Variables:
38 */
39
40 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
41
42 /*******************************************************************************
43 * Local module support methods
44 */
45
46 static void resize_frame_rect(HWND hWnd, PRECT prect)
47 {
48 RECT rt;
49 /*
50 if (IsWindowVisible(hToolBar)) {
51 SendMessage(hToolBar, WM_SIZE, 0, 0);
52 GetClientRect(hToolBar, &rt);
53 prect->top = rt.bottom+3;
54 prect->bottom -= rt.bottom+3;
55 }
56 */
57 if (IsWindowVisible(hStatusBar)) {
58 SetupStatusBar(hWnd, TRUE);
59 GetClientRect(hStatusBar, &rt);
60 prect->bottom -= rt.bottom;
61 }
62 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
63 }
64
65 static void resize_frame_client(HWND hWnd)
66 {
67 RECT rect;
68
69 GetClientRect(hWnd, &rect);
70 resize_frame_rect(hWnd, &rect);
71 }
72
73 /********************************************************************************/
74
75 static void OnInitMenu(HWND hWnd)
76 {
77 LONG lResult;
78 HKEY hKey = NULL;
79 DWORD dwIndex, cbValueName, cbValueData, dwType;
80 TCHAR szValueName[256];
81 BYTE abValueData[256];
82 int nFavoriteMenuPos = 3;
83 static int s_nFavoriteMenuSubPos = -1;
84 HMENU hMenu;
85 BOOL bDisplayedAny = FALSE;
86
87 /* Find Favorites menu and clear it out */
88 hMenu = GetSubMenu(GetMenu(hWnd), nFavoriteMenuPos);
89 if (!hMenu)
90 goto done;
91 if (s_nFavoriteMenuSubPos < 0)
92 {
93 s_nFavoriteMenuSubPos = GetMenuItemCount(hMenu);
94 }
95 else
96 {
97 while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION))
98 ;
99 }
100
101 lResult = RegOpenKey(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites"), &hKey);
102 if (lResult != ERROR_SUCCESS)
103 goto done;
104
105 dwIndex = 0;
106 do
107 {
108 cbValueName = sizeof(szValueName) / sizeof(szValueName[0]);
109 cbValueData = sizeof(abValueData);
110 lResult = RegEnumValue(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
111 if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
112 {
113 if (!bDisplayedAny)
114 {
115 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
116 bDisplayedAny = TRUE;
117 }
118 AppendMenu(hMenu, MF_GRAYED, 0, szValueName);
119 }
120 dwIndex++;
121 }
122 while(lResult == ERROR_SUCCESS);
123
124 done:
125 if (hKey)
126 RegCloseKey(hKey);
127 }
128
129 static void OnEnterMenuLoop(HWND hWnd)
130 {
131 int nParts;
132
133 /* Update the status bar pane sizes */
134 nParts = -1;
135 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
136 bInMenuLoop = TRUE;
137 SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
138 }
139
140 static void OnExitMenuLoop(HWND hWnd)
141 {
142 bInMenuLoop = FALSE;
143 /* Update the status bar pane sizes*/
144 SetupStatusBar(hWnd, TRUE);
145 UpdateStatusBar();
146 }
147
148 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
149 {
150 TCHAR str[100];
151
152 _tcscpy(str, _T(""));
153 if (nFlags & MF_POPUP) {
154 if (hSysMenu != GetMenu(hWnd)) {
155 if (nItemID == 2) nItemID = 5;
156 }
157 }
158 if (LoadString(hInst, nItemID, str, 100)) {
159 /* load appropriate string*/
160 LPTSTR lpsz = str;
161 /* first newline terminates actual string*/
162 lpsz = _tcschr(lpsz, '\n');
163 if (lpsz != NULL)
164 *lpsz = '\0';
165 }
166 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
167 }
168
169 void SetupStatusBar(HWND hWnd, BOOL bResize)
170 {
171 RECT rc;
172 int nParts;
173 GetClientRect(hWnd, &rc);
174 nParts = rc.right;
175 /* nParts = -1;*/
176 if (bResize)
177 SendMessage(hStatusBar, WM_SIZE, 0, 0);
178 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
179 }
180
181 void UpdateStatusBar(void)
182 {
183 TCHAR text[260];
184 DWORD size;
185
186 size = sizeof(text)/sizeof(TCHAR);
187 GetComputerName(text, &size);
188 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
189 }
190
191 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
192 {
193 BOOL vis = IsWindowVisible(hchild);
194 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
195
196 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
197 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
198 resize_frame_client(hWnd);
199 }
200
201 static BOOL CheckCommDlgError(HWND hWnd)
202 {
203 DWORD dwErrorCode = CommDlgExtendedError();
204 switch (dwErrorCode) {
205 case CDERR_DIALOGFAILURE:
206 break;
207 case CDERR_FINDRESFAILURE:
208 break;
209 case CDERR_NOHINSTANCE:
210 break;
211 case CDERR_INITIALIZATION:
212 break;
213 case CDERR_NOHOOK:
214 break;
215 case CDERR_LOCKRESFAILURE:
216 break;
217 case CDERR_NOTEMPLATE:
218 break;
219 case CDERR_LOADRESFAILURE:
220 break;
221 case CDERR_STRUCTSIZE:
222 break;
223 case CDERR_LOADSTRFAILURE:
224 break;
225 case FNERR_BUFFERTOOSMALL:
226 break;
227 case CDERR_MEMALLOCFAILURE:
228 break;
229 case FNERR_INVALIDFILENAME:
230 break;
231 case CDERR_MEMLOCKFAILURE:
232 break;
233 case FNERR_SUBCLASSFAILURE:
234 break;
235 default:
236 break;
237 }
238 return TRUE;
239 }
240
241 #define MAX_CUSTOM_FILTER_SIZE 50
242 TCHAR CustomFilterBuffer[MAX_CUSTOM_FILTER_SIZE];
243 TCHAR FileNameBuffer[_MAX_PATH];
244 TCHAR FileTitleBuffer[_MAX_PATH];
245
246 typedef struct
247 {
248 UINT DisplayID;
249 UINT FilterID;
250 } FILTERPAIR, *PFILTERPAIR;
251
252 void
253 BuildFilterStrings(TCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
254 {
255 int i, c;
256
257 c = 0;
258 for(i = 0; i < PairCount; i++)
259 {
260 c += LoadString(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(TCHAR));
261 Filter[++c] = '\0';
262 c += LoadString(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(TCHAR));
263 Filter[++c] = '\0';
264 }
265 Filter[++c] = '\0';
266 }
267
268 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
269 {
270 FILTERPAIR FilterPairs[3];
271 static TCHAR Filter[1024];
272
273 memset(pofn, 0, sizeof(OPENFILENAME));
274 pofn->lStructSize = sizeof(OPENFILENAME);
275 pofn->hwndOwner = hWnd;
276 pofn->hInstance = hInst;
277
278 /* create filter string */
279 FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
280 FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
281 FilterPairs[1].DisplayID = IDS_FLT_REGEDIT4;
282 FilterPairs[1].FilterID = IDS_FLT_REGEDIT4_FLT;
283 FilterPairs[2].DisplayID = IDS_FLT_ALLFILES;
284 FilterPairs[2].FilterID = IDS_FLT_ALLFILES_FLT;
285 BuildFilterStrings(Filter, FilterPairs, sizeof(FilterPairs) / sizeof(FILTERPAIR));
286
287 pofn->lpstrFilter = Filter;
288 pofn->lpstrCustomFilter = CustomFilterBuffer;
289 pofn->nMaxCustFilter = MAX_CUSTOM_FILTER_SIZE;
290 pofn->nFilterIndex = 0;
291 pofn->lpstrFile = FileNameBuffer;
292 pofn->nMaxFile = _MAX_PATH;
293 pofn->lpstrFileTitle = FileTitleBuffer;
294 pofn->nMaxFileTitle = _MAX_PATH;
295 /* pofn->lpstrInitialDir = _T("");*/
296 /* pofn->lpstrTitle = _T("Import Registry File");*/
297 /* pofn->Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER + OFN_ENABLESIZING;*/
298 pofn->Flags = OFN_HIDEREADONLY;
299 /* pofn->nFileOffset = ;*/
300 /* pofn->nFileExtension = ;*/
301 /* pofn->lpstrDefExt = _T("");*/
302 /* pofn->lCustData = ;*/
303 /* pofn->lpfnHook = ImportRegistryFile_OFNHookProc;*/
304 /* pofn->lpTemplateName = _T("ID_DLG_IMPORT_REGFILE");*/
305 /* pofn->lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);*/
306 /* pofn->FlagsEx = ;*/
307 return TRUE;
308 }
309
310 static BOOL ImportRegistryFile(HWND hWnd)
311 {
312 OPENFILENAME ofn;
313 TCHAR Caption[128];
314
315 InitOpenFileName(hWnd, &ofn);
316 LoadString(hInst, IDS_IMPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
317 ofn.lpstrTitle = Caption;
318 /* ofn.lCustData = ;*/
319 if (GetOpenFileName(&ofn)) {
320 /* FIXME - convert to ascii */
321 if (!import_registry_file(ofn.lpstrFile)) {
322 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
323 return FALSE;
324 }
325 #if 0
326 get_file_name(&s, filename, MAX_PATH);
327 if (!filename[0]) {
328 printf("No file name is specified\n%s", usage);
329 return FALSE;
330 /*exit(1);*/
331 }
332 while (filename[0]) {
333 if (!import_registry_file(filename)) {
334 perror("");
335 printf("Can't open file \"%s\"\n", filename);
336 return FALSE;
337 /*exit(1);*/
338 }
339 get_file_name(&s, filename, MAX_PATH);
340 }
341 #endif
342
343 } else {
344 CheckCommDlgError(hWnd);
345 }
346 return TRUE;
347 }
348
349
350 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
351 {
352 HWND hwndExportAll;
353 HWND hwndExportBranch;
354 HWND hwndExportBranchText;
355 UINT_PTR iResult = 0;
356 OPENFILENAME *pOfn;
357 LPTSTR pszSelectedKey;
358 OFNOTIFY *pOfnNotify;
359
360 switch(uiMsg) {
361 case WM_INITDIALOG:
362 pOfn = (OPENFILENAME *) lParam;
363 pszSelectedKey = (LPTSTR) pOfn->lCustData;
364
365 hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
366 if (hwndExportAll)
367 SendMessage(hwndExportAll, BM_SETCHECK, pszSelectedKey[0] ? BST_UNCHECKED : BST_CHECKED, 0);
368
369 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
370 if (hwndExportBranch)
371 SendMessage(hwndExportBranch, BM_SETCHECK, pszSelectedKey[0] ? BST_CHECKED : BST_UNCHECKED, 0);
372
373 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
374 if (hwndExportBranchText)
375 SetWindowText(hwndExportBranchText, pszSelectedKey);
376 break;
377
378 case WM_NOTIFY:
379 if (((NMHDR *) lParam)->code == CDN_FILEOK)
380 {
381 pOfnNotify = (OFNOTIFY *) lParam;
382 pszSelectedKey = (LPTSTR) pOfnNotify->lpOFN->lCustData;
383
384 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
385 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
386 if (hwndExportBranch && hwndExportBranchText
387 && (SendMessage(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
388 {
389 GetWindowText(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
390 }
391 else
392 {
393 pszSelectedKey[0] = '\0';
394 }
395 }
396 break;
397 }
398 return iResult;
399 }
400
401 BOOL ExportRegistryFile(HWND hWnd)
402 {
403 OPENFILENAME ofn;
404 TCHAR ExportKeyPath[_MAX_PATH];
405 TCHAR Caption[128];
406 HKEY hKeyRoot;
407 LPCTSTR pszKeyPath;
408
409 /* Figure out which key path we are exporting */
410 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
411 RegKeyGetName(ExportKeyPath, sizeof(ExportKeyPath) / sizeof(ExportKeyPath[0]),
412 hKeyRoot, pszKeyPath);
413
414 InitOpenFileName(hWnd, &ofn);
415 LoadString(hInst, IDS_EXPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
416 ofn.lpstrTitle = Caption;
417 ofn.lCustData = (LPARAM) ExportKeyPath;
418 ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK;
419 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
420 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORTRANGE);
421 if (GetSaveFileName(&ofn)) {
422 BOOL result;
423 LPSTR pszExportKeyPath;
424 #ifdef UNICODE
425 CHAR buffer[_MAX_PATH];
426
427 WideCharToMultiByte(CP_ACP, 0, ExportKeyPath, -1, buffer, sizeof(buffer), NULL, NULL);
428 pszExportKeyPath = buffer;
429 #else
430 pszExportKeyPath = ExportKeyPath;
431 #endif
432
433 result = export_registry_key(ofn.lpstrFile, pszExportKeyPath);
434 if (!result) {
435 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
436 return FALSE;
437 }
438 #if 0
439 TCHAR filename[MAX_PATH];
440 filename[0] = '\0';
441 get_file_name(&s, filename, MAX_PATH);
442 if (!filename[0]) {
443 printf("No file name is specified\n%s", usage);
444 return FALSE;
445 /*exit(1);*/
446 }
447 if (s[0]) {
448 TCHAR reg_key_name[KEY_MAX_LEN];
449 get_file_name(&s, reg_key_name, KEY_MAX_LEN);
450 export_registry_key((CHAR)filename, reg_key_name);
451 } else {
452 export_registry_key(filename, NULL);
453 }
454 #endif
455
456 } else {
457 CheckCommDlgError(hWnd);
458 }
459 return TRUE;
460 }
461
462 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
463 {
464 #if 1
465 PRINTDLG pd;
466
467 ZeroMemory(&pd, sizeof(PRINTDLG));
468 pd.lStructSize = sizeof(PRINTDLG);
469 pd.hwndOwner = hWnd;
470 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
471 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
472 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
473 pd.nCopies = 1;
474 pd.nFromPage = 0xFFFF;
475 pd.nToPage = 0xFFFF;
476 pd.nMinPage = 1;
477 pd.nMaxPage = 0xFFFF;
478 if (PrintDlg(&pd)) {
479 /* GDI calls to render output. */
480 DeleteDC(pd.hDC); /* Delete DC when done.*/
481 }
482 #else
483 HRESULT hResult;
484 PRINTDLGEX pd;
485
486 hResult = PrintDlgEx(&pd);
487 if (hResult == S_OK) {
488 switch (pd.dwResultAction) {
489 case PD_RESULT_APPLY:
490 /*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. */
491 break;
492 case PD_RESULT_CANCEL:
493 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
494 break;
495 case PD_RESULT_PRINT:
496 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
497 break;
498 default:
499 break;
500 }
501 } else {
502 switch (hResult) {
503 case E_OUTOFMEMORY:
504 /*Insufficient memory. */
505 break;
506 case E_INVALIDARG:
507 /* One or more arguments are invalid. */
508 break;
509 case E_POINTER:
510 /*Invalid pointer. */
511 break;
512 case E_HANDLE:
513 /*Invalid handle. */
514 break;
515 case E_FAIL:
516 /*Unspecified error. */
517 break;
518 default:
519 break;
520 }
521 return FALSE;
522 }
523 #endif
524 return TRUE;
525 }
526
527 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
528 {
529 BOOL bClipboardOpened = FALSE;
530 BOOL bSuccess = FALSE;
531 TCHAR szBuffer[512];
532 HGLOBAL hGlobal;
533 LPTSTR s;
534
535 if (!OpenClipboard(hWnd))
536 goto done;
537 bClipboardOpened = TRUE;
538
539 if (!EmptyClipboard())
540 goto done;
541
542 if (!RegKeyGetName(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), hRootKey, keyName))
543 goto done;
544
545 hGlobal = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
546 if (!hGlobal)
547 goto done;
548
549 s = GlobalLock(hGlobal);
550 _tcscpy(s, szBuffer);
551 GlobalUnlock(hGlobal);
552
553 #ifdef UNICODE
554 SetClipboardData(CF_UNICODETEXT, hGlobal);
555 #else
556 SetClipboardData(CF_TEXT, hGlobal);
557 #endif
558 bSuccess = TRUE;
559
560 done:
561 if (bClipboardOpened)
562 CloseClipboard();
563 return bSuccess;
564 }
565
566 static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
567 {
568 TCHAR szNewValueFormat[128];
569 TCHAR szNewValue[128];
570 int iIndex = 1;
571 BYTE data[128];
572 DWORD dwExistingType, cbData;
573 LONG lResult;
574 HKEY hKey;
575 LVFINDINFO lvfi;
576
577 if (RegOpenKey(hRootKey, pszKeyPath, &hKey) != ERROR_SUCCESS)
578 return FALSE;
579
580 LoadString(hInst, IDS_NEW_VALUE, szNewValueFormat, sizeof(szNewValueFormat)
581 / sizeof(szNewValueFormat[0]));
582
583 do
584 {
585 _sntprintf(szNewValue, sizeof(szNewValue) / sizeof(szNewValue[0]),
586 szNewValueFormat, iIndex++);
587
588 cbData = sizeof(data);
589 lResult = RegQueryValueEx(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
590 }
591 while(lResult == ERROR_SUCCESS);
592
593 switch(dwType) {
594 case REG_DWORD:
595 cbData = sizeof(DWORD);
596 break;
597 case REG_SZ:
598 case REG_EXPAND_SZ:
599 cbData = sizeof(TCHAR);
600 break;
601 case REG_MULTI_SZ:
602 cbData = sizeof(TCHAR) * 2;
603 break;
604 case REG_QWORD:
605 cbData = sizeof(DWORD) * 2;
606 break;
607 default:
608 cbData = 0;
609 break;
610 }
611 memset(data, 0, cbData);
612 lResult = RegSetValueEx(hKey, szNewValue, 0, dwType, data, cbData);
613 if (lResult != ERROR_SUCCESS)
614 return FALSE;
615
616 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
617
618 /* locate the newly added value, and get ready to rename it */
619 memset(&lvfi, 0, sizeof(lvfi));
620 lvfi.flags = LVFI_STRING;
621 lvfi.psz = szNewValue;
622 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
623 if (iIndex >= 0)
624 ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
625
626 return TRUE;
627 }
628
629 static HRESULT
630 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
631 {
632 HRESULT hRet;
633
634 *pDsObjectPicker = NULL;
635
636 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
637 NULL,
638 CLSCTX_INPROC_SERVER,
639 &IID_IDsObjectPicker,
640 (LPVOID*)pDsObjectPicker);
641 if (SUCCEEDED(hRet))
642 {
643 DSOP_INIT_INFO InitInfo;
644 static DSOP_SCOPE_INIT_INFO Scopes[] =
645 {
646 {
647 sizeof(DSOP_SCOPE_INIT_INFO),
648 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
649 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
650 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
651 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
652 0,
653 {
654 {
655 DSOP_FILTER_COMPUTERS,
656 0,
657 0
658 },
659 DSOP_DOWNLEVEL_FILTER_COMPUTERS
660 },
661 NULL,
662 NULL,
663 S_OK
664 },
665 };
666
667 InitInfo.cbSize = sizeof(InitInfo);
668 InitInfo.pwzTargetComputer = NULL;
669 InitInfo.cDsScopeInfos = sizeof(Scopes) / sizeof(Scopes[0]);
670 InitInfo.aDsScopeInfos = Scopes;
671 InitInfo.flOptions = 0;
672 InitInfo.cAttributesToFetch = 0;
673 InitInfo.apwzAttributeNames = NULL;
674
675 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
676 &InitInfo);
677
678 if (FAILED(hRet))
679 {
680 /* delete the object picker in case initialization failed! */
681 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
682 }
683 }
684
685 return hRet;
686 }
687
688 static HRESULT
689 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
690 IN HWND hwndParent OPTIONAL,
691 OUT LPTSTR lpBuffer,
692 IN UINT uSize)
693 {
694 IDataObject *pdo = NULL;
695 HRESULT hRet;
696
697 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
698 hwndParent,
699 &pdo);
700 if (hRet == S_OK)
701 {
702 STGMEDIUM stm;
703 FORMATETC fe;
704
705 fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
706 fe.ptd = NULL;
707 fe.dwAspect = DVASPECT_CONTENT;
708 fe.lindex = -1;
709 fe.tymed = TYMED_HGLOBAL;
710
711 hRet = pdo->lpVtbl->GetData(pdo,
712 &fe,
713 &stm);
714 if (SUCCEEDED(hRet))
715 {
716 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
717 if (SelectionList != NULL)
718 {
719 if (SelectionList->cItems == 1)
720 {
721 UINT nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
722 if (nlen >= uSize)
723 {
724 nlen = uSize - 1;
725 }
726 #if UNICODE
727 memcpy(lpBuffer,
728 SelectionList->aDsSelection[0].pwzName,
729 nlen * sizeof(WCHAR));
730 #else
731 WideCharToMultiByte(CP_ACP,
732 0,
733 SelectionList->aDsSelection[0].pwzName,
734 nlen,
735 lpBuffer,
736 uSize,
737 NULL,
738 NULL);
739 #endif
740 lpBuffer[nlen] = L'\0';
741 }
742
743 GlobalUnlock(stm.hGlobal);
744 }
745
746 ReleaseStgMedium(&stm);
747 }
748
749 pdo->lpVtbl->Release(pdo);
750 }
751
752 return hRet;
753 }
754
755 static VOID
756 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
757 {
758 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
759 }
760
761 /*******************************************************************************
762 *
763 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
764 *
765 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
766 *
767 */
768 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
769 {
770 HKEY hKeyRoot = 0, hKey = 0;
771 LPCTSTR keyPath;
772 LPCTSTR valueName;
773 BOOL result = TRUE;
774 REGSAM regsam = KEY_READ;
775 LONG lRet;
776 int item;
777
778 switch (LOWORD(wParam)) {
779 case ID_REGISTRY_IMPORTREGISTRYFILE:
780 ImportRegistryFile(hWnd);
781 return TRUE;
782 case ID_REGISTRY_EXPORTREGISTRYFILE:
783 ExportRegistryFile(hWnd);
784 return TRUE;
785 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
786 {
787 IDsObjectPicker *ObjectPicker;
788 TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
789 HRESULT hRet;
790
791 hRet = CoInitialize(NULL);
792 if (SUCCEEDED(hRet))
793 {
794 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
795 if (SUCCEEDED(hRet))
796 {
797 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
798 hWnd,
799 szComputerName,
800 sizeof(szComputerName) / sizeof(szComputerName[0]));
801 if (hRet == S_OK)
802 {
803 /* FIXME - connect to the registry */
804 }
805
806 FreeObjectPicker(ObjectPicker);
807 }
808
809 CoUninitialize();
810 }
811
812 return TRUE;
813 }
814 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
815 return TRUE;
816 case ID_REGISTRY_PRINT:
817 PrintRegistryHive(hWnd, _T(""));
818 return TRUE;
819 case ID_REGISTRY_EXIT:
820 DestroyWindow(hWnd);
821 return TRUE;
822 case ID_VIEW_STATUSBAR:
823 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
824 return TRUE;
825 case ID_HELP_HELPTOPICS:
826 WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
827 return TRUE;
828 case ID_HELP_ABOUT:
829 ShowAboutBox(hWnd);
830 return TRUE;
831 case ID_VIEW_SPLIT:
832 {
833 RECT rt;
834 POINT pt, pts;
835 GetClientRect(g_pChildWnd->hWnd, &rt);
836 pt.x = rt.left + g_pChildWnd->nSplitPos;
837 pt.y = (rt.bottom / 2);
838 pts = pt;
839 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
840 {
841 SetCursorPos(pts.x, pts.y);
842 SetCursor(LoadCursor(0, IDC_SIZEWE));
843 SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
844 }
845 return TRUE;
846 }
847 case ID_EDIT_RENAME:
848 case ID_EDIT_MODIFY:
849 case ID_EDIT_MODIFY_BIN:
850 case ID_EDIT_DELETE:
851 regsam |= KEY_WRITE;
852 break;
853 }
854
855 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
856 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
857 if (keyPath) {
858 lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, regsam, &hKey);
859 if (lRet != ERROR_SUCCESS) hKey = 0;
860 }
861
862 switch (LOWORD(wParam)) {
863 case ID_EDIT_MODIFY:
864 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
865 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
866 break;
867 case ID_EDIT_MODIFY_BIN:
868 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
869 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
870 break;
871 case ID_EDIT_RENAME:
872 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
873 {
874 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
875 if(item > -1)
876 {
877 ListView_EditLabel(g_pChildWnd->hListWnd, item);
878 }
879 }
880 break;
881 case ID_EDIT_DELETE:
882 {
883 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
884 if(nSelected >= 1)
885 {
886 TCHAR msg[128], caption[128];
887 LoadString(hInst, IDS_QUERY_DELETE_CONFIRM, caption, sizeof(caption)/sizeof(TCHAR));
888 LoadString(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, sizeof(msg)/sizeof(TCHAR));
889 if(MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
890 {
891 int ni, errs;
892
893 item = -1;
894 errs = 0;
895 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
896 {
897 valueName = GetValueName(g_pChildWnd->hListWnd, item);
898 if(RegDeleteValue(hKey, valueName) != ERROR_SUCCESS)
899 {
900 errs++;
901 }
902 item = ni;
903 }
904
905 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
906 if(errs > 0)
907 {
908 LoadString(hInst, IDS_ERR_DELVAL_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
909 LoadString(hInst, IDS_ERR_DELETEVALUE, msg, sizeof(msg)/sizeof(TCHAR));
910 MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
911 }
912 }
913 }
914 break;
915 case ID_EDIT_NEW_STRINGVALUE:
916 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
917 break;
918 case ID_EDIT_NEW_BINARYVALUE:
919 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
920 break;
921 case ID_EDIT_NEW_DWORDVALUE:
922 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
923 break;
924 }
925 case ID_EDIT_COPYKEYNAME:
926 CopyKeyName(hWnd, hKeyRoot, keyPath);
927 break;
928 case ID_EDIT_PERMISSIONS:
929 if(keyPath != NULL && _tcslen(keyPath) > 0)
930 {
931 RegKeyEditPermissions(hWnd, hKey, NULL, keyPath);
932 }
933 else
934 {
935 MessageBeep(MB_ICONASTERISK);
936 }
937 break;
938 case ID_REGISTRY_PRINTERSETUP:
939 /*PRINTDLG pd;*/
940 /*PrintDlg(&pd);*/
941 /*PAGESETUPDLG psd;*/
942 /*PageSetupDlg(&psd);*/
943 break;
944 case ID_REGISTRY_OPENLOCAL:
945 break;
946
947 case ID_VIEW_REFRESH:
948 RefreshTreeView(g_pChildWnd->hTreeWnd);
949 /*RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL); */
950 break;
951 /*case ID_OPTIONS_TOOLBAR:*/
952 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
953 /* break;*/
954 case ID_EDIT_NEW_KEY:
955 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
956 break;
957 default:
958 result = FALSE;
959 }
960
961 if(hKey)
962 RegCloseKey(hKey);
963 return result;
964 }
965
966 /********************************************************************************
967 *
968 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
969 *
970 * PURPOSE: Processes messages for the main frame window.
971 *
972 * WM_COMMAND - process the application menu
973 * WM_DESTROY - post a quit message and return
974 *
975 */
976
977 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
978 {
979 switch (message) {
980 case WM_CREATE:
981 CreateWindowEx(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
982 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
983 hWnd, (HMENU)0, hInst, 0);
984 break;
985 case WM_COMMAND:
986 if (!_CmdWndProc(hWnd, message, wParam, lParam))
987 return DefWindowProc(hWnd, message, wParam, lParam);
988 break;
989 case WM_ACTIVATE:
990 if (LOWORD(hWnd))
991 SetFocus(g_pChildWnd->hWnd);
992 break;
993 case WM_SIZE:
994 resize_frame_client(hWnd);
995 break;
996 case WM_TIMER:
997 break;
998 case WM_INITMENU:
999 OnInitMenu(hWnd);
1000 break;
1001 case WM_ENTERMENULOOP:
1002 OnEnterMenuLoop(hWnd);
1003 break;
1004 case WM_EXITMENULOOP:
1005 OnExitMenuLoop(hWnd);
1006 break;
1007 case WM_MENUSELECT:
1008 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1009 break;
1010 case WM_DESTROY:
1011 WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
1012 PostQuitMessage(0);
1013 default:
1014 return DefWindowProc(hWnd, message, wParam, lParam);
1015 }
1016 return 0;
1017 }