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