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