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