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