1 /*
2 * Regedit frame window
3 *
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
6 */
7
8 #include "regedit.h"
9
10 #include <commdlg.h>
11 #include <cderr.h>
12 #include <objsel.h>
13
14 #define FAVORITES_MENU_POSITION 3
15 static WCHAR s_szFavoritesRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
16 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
17 extern WCHAR Suggestions[256];
18
ErrorBox(HWND hWnd,UINT Error)19 static UINT ErrorBox(HWND hWnd, UINT Error)
20 {
21 WCHAR buf[400];
22 if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
23 NULL, Error, 0, buf, _countof(buf), NULL))
24 *(UINT*)buf = L'?';
25 MessageBoxW(hWnd, buf, NULL, MB_ICONSTOP);
26 return Error;
27 }
28
resize_frame_rect(HWND hWnd,PRECT prect)29 static void resize_frame_rect(HWND hWnd, PRECT prect)
30 {
31 if (IsWindowVisible(hStatusBar))
32 {
33 RECT rt;
34
35 SetupStatusBar(hWnd, TRUE);
36 GetWindowRect(hStatusBar, &rt);
37 prect->bottom -= rt.bottom - rt.top;
38 }
39 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
40 }
41
resize_frame_client(HWND hWnd)42 static void resize_frame_client(HWND hWnd)
43 {
44 RECT rect;
45
46 GetClientRect(hWnd, &rect);
47 resize_frame_rect(hWnd, &rect);
48 }
49
OnInitMenu(HWND hWnd)50 static void OnInitMenu(HWND hWnd)
51 {
52 LONG lResult;
53 HKEY hKey = NULL;
54 DWORD dwIndex, cbValueName, cbValueData, dwType;
55 WCHAR szValueName[256];
56 BYTE abValueData[256];
57 static int s_nFavoriteMenuSubPos = -1;
58 HMENU hMenu;
59 BOOL bDisplayedAny = FALSE;
60 HTREEITEM hSelTreeItem;
61 BOOL bCanAddFav;
62
63 /* Find Favorites menu and clear it out */
64 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
65 if (!hMenu)
66 goto done;
67 if (s_nFavoriteMenuSubPos < 0)
68 {
69 s_nFavoriteMenuSubPos = GetMenuItemCount(hMenu);
70 }
71 else
72 {
73 while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION)) ;
74 }
75
76 hSelTreeItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
77 bCanAddFav = TreeView_GetParent(g_pChildWnd->hTreeWnd, hSelTreeItem) != NULL;
78 EnableMenuItem(GetMenu(hWnd), ID_FAVOURITES_ADDTOFAVOURITES,
79 MF_BYCOMMAND | (bCanAddFav ? MF_ENABLED : MF_GRAYED));
80
81 lResult = RegOpenKeyW(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
82 if (lResult != ERROR_SUCCESS)
83 goto done;
84
85 dwIndex = 0;
86 do
87 {
88 cbValueName = ARRAY_SIZE(szValueName);
89 cbValueData = sizeof(abValueData);
90 lResult = RegEnumValueW(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
91 if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
92 {
93 if (!bDisplayedAny)
94 {
95 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
96 bDisplayedAny = TRUE;
97 }
98 AppendMenu(hMenu, 0, ID_FAVORITES_MIN + GetMenuItemCount(hMenu), szValueName);
99 }
100 dwIndex++;
101 }
102 while(lResult == ERROR_SUCCESS);
103
104 done:
105 if (hKey)
106 RegCloseKey(hKey);
107 }
108
OnEnterMenuLoop(HWND hWnd)109 static void OnEnterMenuLoop(HWND hWnd)
110 {
111 int nParts;
112 UNREFERENCED_PARAMETER(hWnd);
113
114 /* Update the status bar pane sizes */
115 nParts = -1;
116 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
117 bInMenuLoop = TRUE;
118 SendMessageW(hStatusBar, SB_SETTEXTW, (WPARAM)0, (LPARAM)L"");
119 }
120
OnExitMenuLoop(HWND hWnd)121 static void OnExitMenuLoop(HWND hWnd)
122 {
123 bInMenuLoop = FALSE;
124 /* Update the status bar pane sizes*/
125 SetupStatusBar(hWnd, TRUE);
126 UpdateStatusBar();
127 }
128
OnMenuSelect(HWND hWnd,UINT nItemID,UINT nFlags,HMENU hSysMenu)129 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
130 {
131 WCHAR str[100];
132
133 str[0] = UNICODE_NULL;
134 if (nFlags & MF_POPUP)
135 {
136 if (hSysMenu != GetMenu(hWnd))
137 {
138 if (nItemID == 2) nItemID = 5;
139 }
140 }
141 if (LoadStringW(hInst, nItemID, str, 100))
142 {
143 /* load appropriate string*/
144 LPWSTR lpsz = str;
145 /* first newline terminates actual string*/
146 lpsz = wcschr(lpsz, L'\n');
147 if (lpsz != NULL)
148 *lpsz = L'\0';
149 }
150 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
151 }
152
SetupStatusBar(HWND hWnd,BOOL bResize)153 void SetupStatusBar(HWND hWnd, BOOL bResize)
154 {
155 RECT rc;
156 int nParts;
157 GetClientRect(hWnd, &rc);
158 nParts = rc.right;
159 /* nParts = -1;*/
160 if (bResize)
161 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
162 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
163 }
164
UpdateStatusBar(void)165 void UpdateStatusBar(void)
166 {
167 HKEY hKeyRoot;
168 LPCWSTR pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
169
170 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)pszKeyPath);
171 }
172
toggle_child(HWND hWnd,UINT cmd,HWND hchild)173 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
174 {
175 BOOL vis = IsWindowVisible(hchild);
176 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
177
178 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
179 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
180 resize_frame_client(hWnd);
181 }
182
CheckCommDlgError(HWND hWnd)183 static BOOL CheckCommDlgError(HWND hWnd)
184 {
185 DWORD dwErrorCode = CommDlgExtendedError();
186 UNREFERENCED_PARAMETER(hWnd);
187 switch (dwErrorCode)
188 {
189 case CDERR_DIALOGFAILURE:
190 break;
191 case CDERR_FINDRESFAILURE:
192 break;
193 case CDERR_NOHINSTANCE:
194 break;
195 case CDERR_INITIALIZATION:
196 break;
197 case CDERR_NOHOOK:
198 break;
199 case CDERR_LOCKRESFAILURE:
200 break;
201 case CDERR_NOTEMPLATE:
202 break;
203 case CDERR_LOADRESFAILURE:
204 break;
205 case CDERR_STRUCTSIZE:
206 break;
207 case CDERR_LOADSTRFAILURE:
208 break;
209 case FNERR_BUFFERTOOSMALL:
210 break;
211 case CDERR_MEMALLOCFAILURE:
212 break;
213 case FNERR_INVALIDFILENAME:
214 break;
215 case CDERR_MEMLOCKFAILURE:
216 break;
217 case FNERR_SUBCLASSFAILURE:
218 break;
219 default:
220 break;
221 }
222 return TRUE;
223 }
224
225 WCHAR FileNameBuffer[MAX_PATH];
226
227 typedef struct
228 {
229 UINT DisplayID;
230 UINT FilterID;
231 } FILTERPAIR, *PFILTERPAIR;
232
233 void
BuildFilterStrings(WCHAR * Filter,PFILTERPAIR Pairs,int PairCount)234 BuildFilterStrings(WCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
235 {
236 int i, c;
237
238 c = 0;
239 for(i = 0; i < PairCount; i++)
240 {
241 c += LoadStringW(hInst, Pairs[i].DisplayID, &Filter[c], 255);
242 Filter[++c] = L'\0';
243 c += LoadStringW(hInst, Pairs[i].FilterID, &Filter[c], 255);
244 Filter[++c] = L'\0';
245 }
246 Filter[++c] = L'\0';
247 }
248
InitOpenFileName(HWND hWnd,OPENFILENAME * pofn,BOOL bSave)249 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn, BOOL bSave)
250 {
251 FILTERPAIR FilterPairs[5];
252 static WCHAR Filter[1024];
253
254 memset(pofn, 0, sizeof(OPENFILENAME));
255 pofn->lStructSize = sizeof(OPENFILENAME);
256 pofn->hwndOwner = hWnd;
257 pofn->hInstance = hInst;
258
259 /* create filter string */
260 FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
261 FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
262 FilterPairs[1].DisplayID = IDS_FLT_HIVFILES;
263 FilterPairs[1].FilterID = IDS_FLT_HIVFILES_FLT;
264 FilterPairs[2].DisplayID = IDS_FLT_REGEDIT4;
265 FilterPairs[2].FilterID = IDS_FLT_REGEDIT4_FLT;
266 if (bSave)
267 {
268 FilterPairs[3].DisplayID = IDS_FLT_TXTFILES;
269 FilterPairs[3].FilterID = IDS_FLT_TXTFILES_FLT;
270 FilterPairs[4].DisplayID = IDS_FLT_ALLFILES;
271 FilterPairs[4].FilterID = IDS_FLT_ALLFILES_FLT;
272 }
273 else
274 {
275 FilterPairs[3].DisplayID = IDS_FLT_ALLFILES;
276 FilterPairs[3].FilterID = IDS_FLT_ALLFILES_FLT;
277 }
278
279 BuildFilterStrings(Filter, FilterPairs, ARRAY_SIZE(FilterPairs) - !bSave);
280
281 pofn->lpstrFilter = Filter;
282 pofn->lpstrFile = FileNameBuffer;
283 pofn->nMaxFile = _countof(FileNameBuffer);
284 pofn->Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
285 pofn->lpstrDefExt = L"reg";
286 if (bSave)
287 pofn->Flags |= OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
288 else
289 pofn->Flags |= OFN_FILEMUSTEXIST;
290
291 return TRUE;
292 }
293
294 #define LOADHIVE_KEYNAMELENGTH 128
295
LoadHive_KeyNameInHookProc(HWND hWndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)296 static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
297 {
298 static LPWSTR sKey = NULL;
299 switch(uMsg)
300 {
301 case WM_INITDIALOG:
302 sKey = (LPWSTR)lParam;
303 break;
304 case WM_COMMAND:
305 switch(LOWORD(wParam))
306 {
307 case IDOK:
308 if(GetDlgItemTextW(hWndDlg, IDC_EDIT_KEY, sKey, LOADHIVE_KEYNAMELENGTH))
309 return EndDialog(hWndDlg, -1);
310 else
311 return EndDialog(hWndDlg, 0);
312 case IDCANCEL:
313 return EndDialog(hWndDlg, 0);
314 }
315 break;
316 }
317 return FALSE;
318 }
319
EnablePrivilege(LPCWSTR lpszPrivilegeName,LPCWSTR lpszSystemName,BOOL bEnablePrivilege)320 static BOOL EnablePrivilege(LPCWSTR lpszPrivilegeName, LPCWSTR lpszSystemName, BOOL bEnablePrivilege)
321 {
322 BOOL bRet = FALSE;
323 HANDLE hToken = NULL;
324
325 if (OpenProcessToken(GetCurrentProcess(),
326 TOKEN_ADJUST_PRIVILEGES,
327 &hToken))
328 {
329 TOKEN_PRIVILEGES tp;
330
331 tp.PrivilegeCount = 1;
332 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
333
334 if (LookupPrivilegeValueW(lpszSystemName,
335 lpszPrivilegeName,
336 &tp.Privileges[0].Luid))
337 {
338 bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
339
340 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
341 bRet = FALSE;
342 }
343
344 CloseHandle(hToken);
345 }
346
347 return bRet;
348 }
349
LoadHive(HWND hWnd)350 static BOOL LoadHive(HWND hWnd)
351 {
352 OPENFILENAME ofn;
353 WCHAR Caption[128];
354 LPCWSTR pszKeyPath;
355 WCHAR xPath[LOADHIVE_KEYNAMELENGTH];
356 HKEY hRootKey;
357 WCHAR Filter[1024];
358 FILTERPAIR filter;
359 /* get the item key to load the hive in */
360 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
361 /* initialize the "open file" dialog */
362 InitOpenFileName(hWnd, &ofn, FALSE);
363 /* build the "All Files" filter up */
364 filter.DisplayID = IDS_FLT_ALLFILES;
365 filter.FilterID = IDS_FLT_ALLFILES_FLT;
366 BuildFilterStrings(Filter, &filter, 1);
367 ofn.lpstrFilter = Filter;
368 /* load and set the caption and flags for dialog */
369 LoadStringW(hInst, IDS_LOAD_HIVE, Caption, ARRAY_SIZE(Caption));
370 ofn.lpstrTitle = Caption;
371 ofn.Flags |= OFN_ENABLESIZING;
372
373 /* now load the hive */
374 if (GetOpenFileName(&ofn))
375 {
376 if (DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_LOADHIVE), hWnd,
377 &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
378 {
379 LONG regLoadResult;
380
381 /* Enable the 'restore' privilege, load the hive, disable the privilege */
382 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
383 regLoadResult = RegLoadKeyW(hRootKey, xPath, ofn.lpstrFile);
384 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
385
386 if(regLoadResult == ERROR_SUCCESS)
387 {
388 /* refresh tree and list views */
389 RefreshTreeView(g_pChildWnd->hTreeWnd);
390 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
391 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath, TRUE);
392 }
393 else
394 {
395 ErrorMessageBox(hWnd, Caption, regLoadResult);
396 return FALSE;
397 }
398 }
399 }
400 else
401 {
402 CheckCommDlgError(hWnd);
403 }
404 return TRUE;
405 }
406
UnloadHive(HWND hWnd)407 static BOOL UnloadHive(HWND hWnd)
408 {
409 WCHAR Caption[128];
410 LPCWSTR pszKeyPath;
411 HKEY hRootKey;
412 LONG regUnloadResult;
413
414 /* get the item key to unload */
415 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
416 /* load and set the caption and flags for dialog */
417 LoadStringW(hInst, IDS_UNLOAD_HIVE, Caption, ARRAY_SIZE(Caption));
418
419 /* Enable the 'restore' privilege, unload the hive, disable the privilege */
420 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
421 regUnloadResult = RegUnLoadKeyW(hRootKey, pszKeyPath);
422 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
423
424 if(regUnloadResult == ERROR_SUCCESS)
425 {
426 /* refresh tree and list views */
427 RefreshTreeView(g_pChildWnd->hTreeWnd);
428 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
429 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath, TRUE);
430 }
431 else
432 {
433 ErrorMessageBox(hWnd, Caption, regUnloadResult);
434 return FALSE;
435 }
436 return TRUE;
437 }
438
ImportRegistryFile(HWND hWnd)439 static BOOL ImportRegistryFile(HWND hWnd)
440 {
441 BOOL bRet = FALSE;
442 OPENFILENAME ofn;
443 WCHAR Caption[128], szTitle[512], szText[512];
444 HKEY hKeyRoot;
445 LPCWSTR pszKeyPath;
446
447 /* Figure out in which key path we are importing */
448 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
449
450 InitOpenFileName(hWnd, &ofn, FALSE);
451 LoadStringW(hInst, IDS_IMPORT_REG_FILE, Caption, ARRAY_SIZE(Caption));
452 ofn.lpstrTitle = Caption;
453 ofn.Flags |= OFN_ENABLESIZING;
454
455 if (GetOpenFileName(&ofn))
456 {
457 /* Look at the extension of the file to determine its type */
458 if (ofn.nFileExtension >= 1 &&
459 _wcsicmp(ofn.lpstrFile + ofn.nFileExtension, L"reg") == 0) /* REGEDIT4 or Windows Registry Editor Version 5.00 */
460 {
461 /* Open the file */
462 FILE* fp = _wfopen(ofn.lpstrFile, L"rb");
463
464 /* Import it */
465 if (fp == NULL || !import_registry_file(fp))
466 {
467 /* Error opening the file */
468 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
469 LoadStringW(hInst, IDS_IMPORT_ERROR, szText, ARRAY_SIZE(szText));
470 InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
471 bRet = FALSE;
472 }
473 else
474 {
475 /* Show successful import */
476 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
477 LoadStringW(hInst, IDS_IMPORT_OK, szText, ARRAY_SIZE(szText));
478 InfoMessageBox(hWnd, MB_OK | MB_ICONINFORMATION, szTitle, szText, ofn.lpstrFile);
479 bRet = TRUE;
480 }
481
482 /* Close the file */
483 if (fp) fclose(fp);
484 }
485 else /* Registry Hive Files */
486 {
487 LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_CAPTION, szTitle, ARRAY_SIZE(szTitle));
488 LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_MSG, szText, ARRAY_SIZE(szText));
489
490 /* Display a confirmation message */
491 if (MessageBoxW(g_pChildWnd->hWnd, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDYES)
492 {
493 LONG lResult;
494 HKEY hSubKey;
495
496 /* Open the subkey */
497 lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_WRITE, &hSubKey);
498 if (lResult == ERROR_SUCCESS)
499 {
500 /* Enable the 'restore' privilege, restore the hive then disable the privilege */
501 EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
502 lResult = RegRestoreKey(hSubKey, ofn.lpstrFile, REG_FORCE_RESTORE);
503 EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
504
505 /* Flush the subkey and close it */
506 RegFlushKey(hSubKey);
507 RegCloseKey(hSubKey);
508 }
509
510 /* Set the return value */
511 bRet = (lResult == ERROR_SUCCESS);
512
513 /* Display error, if any */
514 if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
515 }
516 }
517 }
518 else
519 {
520 CheckCommDlgError(hWnd);
521 }
522
523 /* refresh tree and list views */
524 RefreshTreeView(g_pChildWnd->hTreeWnd);
525 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
526 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, pszKeyPath, TRUE);
527
528 return bRet;
529 }
530
ExportRegistryFile_OFNHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam)531 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
532 {
533 HWND hwndExportAll;
534 HWND hwndExportBranch;
535 HWND hwndExportBranchText;
536 UINT_PTR iResult = 0;
537 OPENFILENAME *pOfn;
538 LPWSTR pszSelectedKey;
539 OFNOTIFY *pOfnNotify;
540
541 UNREFERENCED_PARAMETER(wParam);
542
543 switch(uiMsg)
544 {
545 case WM_INITDIALOG:
546 pOfn = (OPENFILENAME *) lParam;
547 pszSelectedKey = (LPWSTR) pOfn->lCustData;
548
549 hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
550 if (hwndExportAll)
551 SendMessageW(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
552
553 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
554 if (hwndExportBranch)
555 SendMessageW(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
556
557 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
558 if (hwndExportBranchText)
559 SetWindowTextW(hwndExportBranchText, pszSelectedKey);
560 break;
561
562 case WM_NOTIFY:
563 if (((NMHDR *) lParam)->code == CDN_FILEOK)
564 {
565 pOfnNotify = (OFNOTIFY *) lParam;
566 pszSelectedKey = (LPWSTR) pOfnNotify->lpOFN->lCustData;
567
568 hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
569 hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
570 if (hwndExportBranch && hwndExportBranchText
571 && (SendMessageW(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
572 {
573 GetWindowTextW(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
574 }
575 else if (pszSelectedKey)
576 {
577 pszSelectedKey[0] = L'\0';
578 }
579 }
580 break;
581 }
582 return iResult;
583 }
584
ExportRegistryFile(HWND hWnd)585 BOOL ExportRegistryFile(HWND hWnd)
586 {
587 BOOL bRet = FALSE;
588 OPENFILENAME ofn;
589 WCHAR ExportKeyPath[_MAX_PATH] = {0};
590 WCHAR Caption[128], szTitle[512], szText[512];
591 HKEY hKeyRoot;
592 LPCWSTR pszKeyPath;
593
594 /* Figure out which key path we are exporting */
595 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
596 GetKeyName(ExportKeyPath, ARRAY_SIZE(ExportKeyPath), hKeyRoot, pszKeyPath);
597
598 InitOpenFileName(hWnd, &ofn, TRUE);
599 LoadStringW(hInst, IDS_EXPORT_REG_FILE, Caption, ARRAY_SIZE(Caption));
600 ofn.lpstrTitle = Caption;
601
602 /* Only set the path if a key (not the root node) is selected */
603 if (hKeyRoot != 0)
604 {
605 ofn.lCustData = (LPARAM) ExportKeyPath;
606 }
607 ofn.Flags |= OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
608 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
609 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORTRANGE);
610 if (GetSaveFileName(&ofn))
611 {
612 switch (ofn.nFilterIndex)
613 {
614 case 2: /* Registry Hive Files */
615 {
616 LONG lResult;
617 HKEY hSubKey;
618
619 /* Open the subkey */
620 lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_READ, &hSubKey);
621 if (lResult == ERROR_SUCCESS)
622 {
623 /* Enable the 'backup' privilege, save the hive then disable the privilege */
624 EnablePrivilege(SE_BACKUP_NAME, NULL, TRUE);
625 lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
626 if (lResult == ERROR_ALREADY_EXISTS)
627 {
628 /*
629 * We are here, that means that we already said "yes" to the confirmation dialog.
630 * So we absolutely want to replace the hive file.
631 */
632 if (DeleteFileW(ofn.lpstrFile))
633 {
634 /* Try again */
635 lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
636 }
637 }
638 EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
639
640 if (lResult != ERROR_SUCCESS)
641 {
642 /*
643 * If we are here, it's because RegSaveKeyW has failed for any reason.
644 * The problem is that even if it has failed, it has created or
645 * replaced the exported hive file with a new empty file. We don't
646 * want to keep this file, so we delete it.
647 */
648 DeleteFileW(ofn.lpstrFile);
649 }
650
651 /* Close the subkey */
652 RegCloseKey(hSubKey);
653 }
654
655 /* Set the return value */
656 bRet = (lResult == ERROR_SUCCESS);
657
658 /* Display error, if any */
659 if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
660
661 break;
662 }
663
664 case 1: /* Windows Registry Editor Version 5.00 */
665 case 3: /* REGEDIT4 */
666 default: /* All files ==> use Windows Registry Editor Version 5.00 */
667 {
668 if (!export_registry_key(ofn.lpstrFile, ExportKeyPath,
669 (ofn.nFilterIndex == 3 ? REG_FORMAT_4
670 : REG_FORMAT_5)))
671 {
672 /* Error creating the file */
673 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
674 LoadStringW(hInst, IDS_EXPORT_ERROR, szText, ARRAY_SIZE(szText));
675 InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
676 bRet = FALSE;
677 }
678 else
679 {
680 bRet = TRUE;
681 }
682
683 break;
684 }
685
686 case 4: /* Text File */
687 {
688 bRet = txt_export_registry_key(ofn.lpstrFile, ExportKeyPath);
689 if (!bRet)
690 {
691 /* Error creating the file */
692 LoadStringW(hInst, IDS_APP_TITLE, szTitle, ARRAY_SIZE(szTitle));
693 LoadStringW(hInst, IDS_EXPORT_ERROR, szText, ARRAY_SIZE(szText));
694 InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
695 }
696 break;
697 }
698 }
699 }
700 else
701 {
702 CheckCommDlgError(hWnd);
703 }
704
705 return bRet;
706 }
707
PrintRegistryHive(HWND hWnd,LPWSTR path)708 BOOL PrintRegistryHive(HWND hWnd, LPWSTR path)
709 {
710 #if 1
711 PRINTDLG pd;
712 UNREFERENCED_PARAMETER(path);
713
714 ZeroMemory(&pd, sizeof(PRINTDLG));
715 pd.lStructSize = sizeof(PRINTDLG);
716 pd.hwndOwner = hWnd;
717 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
718 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
719 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
720 pd.nCopies = 1;
721 pd.nFromPage = 0xFFFF;
722 pd.nToPage = 0xFFFF;
723 pd.nMinPage = 1;
724 pd.nMaxPage = 0xFFFF;
725 if (PrintDlg(&pd))
726 {
727 /* GDI calls to render output. */
728 DeleteDC(pd.hDC); /* Delete DC when done.*/
729 }
730 #else
731 HRESULT hResult;
732 PRINTDLGEX pd;
733
734 hResult = PrintDlgEx(&pd);
735 if (hResult == S_OK)
736 {
737 switch (pd.dwResultAction)
738 {
739 case PD_RESULT_APPLY:
740 /*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. */
741 break;
742 case PD_RESULT_CANCEL:
743 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
744 break;
745 case PD_RESULT_PRINT:
746 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
747 break;
748 default:
749 break;
750 }
751 }
752 else
753 {
754 switch (hResult)
755 {
756 case E_OUTOFMEMORY:
757 /*Insufficient memory. */
758 break;
759 case E_INVALIDARG:
760 /* One or more arguments are invalid. */
761 break;
762 case E_POINTER:
763 /*Invalid pointer. */
764 break;
765 case E_HANDLE:
766 /*Invalid handle. */
767 break;
768 case E_FAIL:
769 /*Unspecified error. */
770 break;
771 default:
772 break;
773 }
774 return FALSE;
775 }
776 #endif
777 return TRUE;
778 }
779
ChooseFavorite(LPCWSTR pszFavorite)780 static void ChooseFavorite(LPCWSTR pszFavorite)
781 {
782 HKEY hKey = NULL;
783 WCHAR szFavoritePath[512];
784 DWORD cbData, dwType;
785
786 if (RegOpenKeyExW(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
787 goto done;
788
789 cbData = sizeof(szFavoritePath);
790 memset(szFavoritePath, 0, sizeof(szFavoritePath));
791 if (RegQueryValueExW(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
792 goto done;
793
794 if (dwType == REG_SZ)
795 SelectNode(g_pChildWnd->hTreeWnd, szFavoritePath);
796
797 done:
798 if (hKey)
799 RegCloseKey(hKey);
800 }
801
GetItemFullPath(HTREEITEM hTI)802 static LPWSTR GetItemFullPath(HTREEITEM hTI)
803 {
804 HKEY hRoot;
805 WCHAR rootname[MAX_PATH], *buffer;
806 SIZE_T rootlen, subkeylen;
807 LPCWSTR subkey = GetItemPath(g_pChildWnd->hTreeWnd, hTI, &hRoot);
808 if (!subkey || !hRoot)
809 return NULL;
810 if (!GetKeyName(rootname, ARRAY_SIZE(rootname), hRoot, L""))
811 return NULL;
812 rootlen = lstrlenW(rootname) + 1; // + 1 for '\\'
813 subkeylen = lstrlenW(subkey);
814 buffer = (WCHAR*)malloc((rootlen + subkeylen + 1) * sizeof(WCHAR));
815 if (buffer)
816 {
817 lstrcpyW(buffer, rootname);
818 buffer[rootlen - 1] = '\\';
819 lstrcpyW(buffer + rootlen, subkey);
820 }
821 return buffer;
822 }
823
AddToFavoritesDlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)824 static INT_PTR CALLBACK AddToFavoritesDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
825 {
826 HWND hName = GetDlgItem(hWnd, IDC_FAVORITENAME);
827 WCHAR name[MAX_PATH];
828 switch (uMsg)
829 {
830 case WM_INITDIALOG:
831 {
832 TVITEM tvi;
833 tvi.mask = TVIF_HANDLE | TVIF_TEXT;
834 tvi.hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
835 tvi.pszText = name;
836 tvi.cchTextMax = _countof(name);
837 if (!TreeView_GetItem(g_pChildWnd->hTreeWnd, &tvi))
838 tvi.pszText[0] = UNICODE_NULL;
839 SetWindowTextW(hName, tvi.pszText);
840 SendMessageW(hName, EM_LIMITTEXT, _countof(name) - 1, 0);
841 return TRUE;
842 }
843 case WM_COMMAND:
844 switch (LOWORD(wParam))
845 {
846 case IDOK:
847 {
848 LPWSTR path;
849 HKEY hKey;
850 DWORD err;
851 if (!GetWindowTextW(hName, name, _countof(name)))
852 {
853 err = GetLastError();
854 goto failed;
855 }
856 path = GetItemFullPath(NULL);
857 if (!path)
858 {
859 err = ERROR_NOT_ENOUGH_MEMORY;
860 goto failed;
861 }
862 err = RegCreateKeyExW(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0,
863 NULL, 0, KEY_SET_VALUE, NULL, &hKey, NULL);
864 if (err)
865 goto failed;
866 err = RegSetValueExW(hKey, name, 0, REG_SZ, (BYTE*)path, (lstrlenW(path) + 1) * sizeof(WCHAR));
867 RegCloseKey(hKey);
868 if (err) failed:
869 ErrorBox(hWnd, err);
870 free(path);
871 return EndDialog(hWnd, err);
872 }
873 case IDCANCEL:
874 return EndDialog(hWnd, ERROR_CANCELLED);
875 case IDC_FAVORITENAME:
876 if (HIWORD(wParam) == EN_UPDATE)
877 EnableWindow(GetDlgItem(hWnd, IDOK), GetWindowTextLengthW(hName) != 0);
878 break;
879 }
880 break;
881 }
882 return FALSE;
883 }
884
CopyKeyName(HWND hWnd,HKEY hRootKey,LPCWSTR keyName)885 BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCWSTR keyName)
886 {
887 BOOL bClipboardOpened = FALSE;
888 BOOL bSuccess = FALSE;
889 WCHAR szBuffer[512];
890 HGLOBAL hGlobal;
891 LPWSTR s;
892 SIZE_T cbGlobal;
893
894 if (!OpenClipboard(hWnd))
895 goto done;
896 bClipboardOpened = TRUE;
897
898 if (!EmptyClipboard())
899 goto done;
900
901 if (!GetKeyName(szBuffer, ARRAY_SIZE(szBuffer), hRootKey, keyName))
902 goto done;
903
904 cbGlobal = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
905 hGlobal = GlobalAlloc(GMEM_MOVEABLE, cbGlobal);
906 if (!hGlobal)
907 goto done;
908
909 s = GlobalLock(hGlobal);
910 StringCbCopyW(s, cbGlobal, szBuffer);
911 GlobalUnlock(hGlobal);
912
913 SetClipboardData(CF_UNICODETEXT, hGlobal);
914 bSuccess = TRUE;
915
916 done:
917 if (bClipboardOpened)
918 CloseClipboard();
919 return bSuccess;
920 }
921
CreateNewValue(HKEY hRootKey,LPCWSTR pszKeyPath,DWORD dwType)922 static BOOL CreateNewValue(HKEY hRootKey, LPCWSTR pszKeyPath, DWORD dwType)
923 {
924 WCHAR szNewValueFormat[128];
925 WCHAR szNewValue[128];
926 int iIndex = 1;
927 BYTE data[128];
928 DWORD dwExistingType, cbData;
929 LONG lResult;
930 HKEY hKey;
931 LVFINDINFO lvfi;
932
933 if (RegOpenKeyExW(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
934 &hKey) != ERROR_SUCCESS)
935 return FALSE;
936
937 LoadStringW(hInst, IDS_NEW_VALUE, szNewValueFormat, ARRAY_SIZE(szNewValueFormat));
938
939 do
940 {
941 wsprintf(szNewValue, szNewValueFormat, iIndex++);
942 cbData = sizeof(data);
943 lResult = RegQueryValueExW(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
944 }
945 while(lResult == ERROR_SUCCESS);
946
947 switch(dwType)
948 {
949 case REG_DWORD:
950 cbData = sizeof(DWORD);
951 break;
952 case REG_SZ:
953 case REG_EXPAND_SZ:
954 cbData = sizeof(WCHAR);
955 break;
956 case REG_MULTI_SZ:
957 /*
958 * WARNING: An empty multi-string has only one null char.
959 * Indeed, multi-strings are built in the following form:
960 * str1\0str2\0...strN\0\0
961 * where each strI\0 is a null-terminated string, and it
962 * ends with a terminating empty string.
963 * Therefore an empty multi-string contains only the terminating
964 * empty string, that is, one null char.
965 */
966 cbData = sizeof(WCHAR);
967 break;
968 case REG_QWORD: /* REG_QWORD_LITTLE_ENDIAN */
969 cbData = sizeof(DWORDLONG); // == sizeof(DWORD) * 2;
970 break;
971 default:
972 cbData = 0;
973 break;
974 }
975 memset(data, 0, cbData);
976 lResult = RegSetValueExW(hKey, szNewValue, 0, dwType, data, cbData);
977 RegCloseKey(hKey);
978 if (lResult != ERROR_SUCCESS)
979 {
980 return FALSE;
981 }
982
983 RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath, TRUE);
984
985 /* locate the newly added value, and get ready to rename it */
986 memset(&lvfi, 0, sizeof(lvfi));
987 lvfi.flags = LVFI_STRING;
988 lvfi.psz = szNewValue;
989 iIndex = ListView_FindItem(g_pChildWnd->hListWnd, -1, &lvfi);
990 if (iIndex >= 0)
991 {
992 ListView_SetItemState(g_pChildWnd->hListWnd, iIndex,
993 LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
994 ListView_EnsureVisible(g_pChildWnd->hListWnd, iIndex, FALSE);
995 (void)ListView_EditLabel(g_pChildWnd->hListWnd, iIndex);
996 }
997
998 return TRUE;
999 }
1000
1001 static HRESULT
InitializeRemoteRegistryPicker(OUT IDsObjectPicker ** pDsObjectPicker)1002 InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
1003 {
1004 HRESULT hRet;
1005
1006 *pDsObjectPicker = NULL;
1007
1008 hRet = CoCreateInstance(&CLSID_DsObjectPicker,
1009 NULL,
1010 CLSCTX_INPROC_SERVER,
1011 &IID_IDsObjectPicker,
1012 (LPVOID*)pDsObjectPicker);
1013 if (SUCCEEDED(hRet))
1014 {
1015 DSOP_INIT_INFO InitInfo;
1016 static DSOP_SCOPE_INIT_INFO Scopes[] =
1017 {
1018 {
1019 sizeof(DSOP_SCOPE_INIT_INFO),
1020 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
1021 DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
1022 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
1023 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
1024 0,
1025 {
1026 {
1027 DSOP_FILTER_COMPUTERS,
1028 0,
1029 0
1030 },
1031 DSOP_DOWNLEVEL_FILTER_COMPUTERS
1032 },
1033 NULL,
1034 NULL,
1035 S_OK
1036 },
1037 };
1038
1039 InitInfo.cbSize = sizeof(InitInfo);
1040 InitInfo.pwzTargetComputer = NULL;
1041 InitInfo.cDsScopeInfos = ARRAY_SIZE(Scopes);
1042 InitInfo.aDsScopeInfos = Scopes;
1043 InitInfo.flOptions = 0;
1044 InitInfo.cAttributesToFetch = 0;
1045 InitInfo.apwzAttributeNames = NULL;
1046
1047 hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
1048 &InitInfo);
1049
1050 if (FAILED(hRet))
1051 {
1052 /* delete the object picker in case initialization failed! */
1053 (*pDsObjectPicker)->lpVtbl->Release(*pDsObjectPicker);
1054 }
1055 }
1056
1057 return hRet;
1058 }
1059
1060 static HRESULT
InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker * pDsObjectPicker,IN HWND hwndParent OPTIONAL,OUT LPWSTR lpBuffer,IN UINT uSize)1061 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
1062 IN HWND hwndParent OPTIONAL,
1063 OUT LPWSTR lpBuffer,
1064 IN UINT uSize)
1065 {
1066 IDataObject *pdo = NULL;
1067 HRESULT hRet;
1068
1069 hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
1070 hwndParent,
1071 &pdo);
1072 if (hRet == S_OK)
1073 {
1074 STGMEDIUM stm;
1075 FORMATETC fe;
1076
1077 fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormatW(CFSTR_DSOP_DS_SELECTION_LIST);
1078 fe.ptd = NULL;
1079 fe.dwAspect = DVASPECT_CONTENT;
1080 fe.lindex = -1;
1081 fe.tymed = TYMED_HGLOBAL;
1082
1083 hRet = pdo->lpVtbl->GetData(pdo,
1084 &fe,
1085 &stm);
1086 if (SUCCEEDED(hRet))
1087 {
1088 PDS_SELECTION_LIST SelectionList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
1089 if (SelectionList != NULL)
1090 {
1091 if (SelectionList->cItems == 1)
1092 {
1093 size_t nlen = wcslen(SelectionList->aDsSelection[0].pwzName);
1094 if (nlen >= uSize)
1095 {
1096 nlen = uSize - 1;
1097 }
1098
1099 memcpy(lpBuffer,
1100 SelectionList->aDsSelection[0].pwzName,
1101 nlen * sizeof(WCHAR));
1102
1103 lpBuffer[nlen] = L'\0';
1104 }
1105
1106 GlobalUnlock(stm.hGlobal);
1107 }
1108
1109 ReleaseStgMedium(&stm);
1110 }
1111
1112 pdo->lpVtbl->Release(pdo);
1113 }
1114
1115 return hRet;
1116 }
1117
1118 static VOID
FreeObjectPicker(IN IDsObjectPicker * pDsObjectPicker)1119 FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
1120 {
1121 pDsObjectPicker->lpVtbl->Release(pDsObjectPicker);
1122 }
1123
1124 /**
1125 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
1126 */
_CmdWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1127 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1128 {
1129 HKEY hKeyRoot = 0, hKey = 0;
1130 LPCWSTR keyPath;
1131 LPCWSTR valueName;
1132 BOOL result = TRUE;
1133 REGSAM regsam = KEY_READ;
1134 int item;
1135
1136 UNREFERENCED_PARAMETER(lParam);
1137 UNREFERENCED_PARAMETER(message);
1138
1139 switch (LOWORD(wParam))
1140 {
1141 case ID_REGISTRY_LOADHIVE:
1142 LoadHive(hWnd);
1143 return TRUE;
1144 case ID_REGISTRY_UNLOADHIVE:
1145 UnloadHive(hWnd);
1146 return TRUE;
1147 case ID_REGISTRY_IMPORTREGISTRYFILE:
1148 ImportRegistryFile(hWnd);
1149 return TRUE;
1150 case ID_REGISTRY_EXPORTREGISTRYFILE:
1151 ExportRegistryFile(hWnd);
1152 return TRUE;
1153 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
1154 {
1155 IDsObjectPicker *ObjectPicker;
1156 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1157 HRESULT hRet;
1158
1159 hRet = CoInitialize(NULL);
1160 if (SUCCEEDED(hRet))
1161 {
1162 hRet = InitializeRemoteRegistryPicker(&ObjectPicker);
1163 if (SUCCEEDED(hRet))
1164 {
1165 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
1166 hWnd,
1167 szComputerName,
1168 ARRAY_SIZE(szComputerName));
1169 if (hRet == S_OK)
1170 {
1171 // FIXME - connect to the registry
1172 }
1173
1174 FreeObjectPicker(ObjectPicker);
1175 }
1176
1177 CoUninitialize();
1178 }
1179
1180 return TRUE;
1181 }
1182 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
1183 return TRUE;
1184 case ID_REGISTRY_PRINT:
1185 PrintRegistryHive(hWnd, L"");
1186 return TRUE;
1187 case ID_REGISTRY_EXIT:
1188 DestroyWindow(hWnd);
1189 return TRUE;
1190 case ID_VIEW_STATUSBAR:
1191 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1192 return TRUE;
1193 case ID_FAVOURITES_ADDTOFAVOURITES:
1194 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_ADDFAVORITES), hWnd, AddToFavoritesDlgProc);
1195 return TRUE;
1196 case ID_HELP_HELPTOPICS:
1197 WinHelpW(hWnd, L"regedit", HELP_FINDER, 0);
1198 return TRUE;
1199 case ID_HELP_ABOUT:
1200 ShowAboutBox(hWnd);
1201 return TRUE;
1202 case ID_VIEW_SPLIT:
1203 {
1204 RECT rt;
1205 POINT pt, pts;
1206 GetClientRect(g_pChildWnd->hWnd, &rt);
1207 pt.x = rt.left + g_pChildWnd->nSplitPos;
1208 pt.y = (rt.bottom / 2);
1209 pts = pt;
1210 if(ClientToScreen(g_pChildWnd->hWnd, &pts))
1211 {
1212 SetCursorPos(pts.x, pts.y);
1213 SetCursor(LoadCursorW(0, IDC_SIZEWE));
1214 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1215 }
1216 return TRUE;
1217 }
1218 case ID_EDIT_RENAME:
1219 case ID_EDIT_MODIFY:
1220 case ID_EDIT_MODIFY_BIN:
1221 case ID_EDIT_DELETE:
1222 regsam |= KEY_WRITE;
1223 break;
1224 }
1225
1226 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1227 valueName = GetValueName(g_pChildWnd->hListWnd, -1);
1228 if (keyPath)
1229 {
1230 if (RegOpenKeyExW(hKeyRoot, keyPath, 0, regsam, &hKey) != ERROR_SUCCESS)
1231 hKey = 0;
1232 }
1233
1234 switch (LOWORD(wParam))
1235 {
1236 case ID_EDIT_MODIFY:
1237 if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
1238 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, FALSE);
1239 break;
1240 case ID_EDIT_MODIFY_BIN:
1241 if (valueName && ModifyValue(hWnd, hKey, valueName, TRUE))
1242 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, FALSE);
1243 break;
1244 case ID_EDIT_RENAME:
1245 if (GetFocus() == g_pChildWnd->hListWnd)
1246 {
1247 if(ListView_GetSelectedCount(g_pChildWnd->hListWnd) == 1)
1248 {
1249 item = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
1250 if(item > -1)
1251 {
1252 (void)ListView_EditLabel(g_pChildWnd->hListWnd, item);
1253 }
1254 }
1255 }
1256 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1257 {
1258 /* Get focused entry of treeview (if any) */
1259 HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
1260 if (hItem != NULL)
1261 (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, hItem);
1262 }
1263 break;
1264 case ID_EDIT_DELETE:
1265 {
1266 if (GetFocus() == g_pChildWnd->hListWnd && hKey)
1267 {
1268 UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
1269 if(nSelected >= 1)
1270 {
1271 WCHAR msg[128], caption[128];
1272 LoadStringW(hInst, IDS_QUERY_DELETE_CONFIRM, caption, ARRAY_SIZE(caption));
1273 LoadStringW(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, ARRAY_SIZE(msg));
1274 if(MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
1275 {
1276 int ni, errs;
1277
1278 item = -1;
1279 errs = 0;
1280 while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
1281 {
1282 valueName = GetValueName(g_pChildWnd->hListWnd, item);
1283 if(RegDeleteValueW(hKey, valueName) != ERROR_SUCCESS)
1284 {
1285 errs++;
1286 }
1287 item = ni;
1288 }
1289
1290 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, FALSE);
1291 if(errs > 0)
1292 {
1293 LoadStringW(hInst, IDS_ERR_DELVAL_CAPTION, caption, ARRAY_SIZE(caption));
1294 LoadStringW(hInst, IDS_ERR_DELETEVALUE, msg, ARRAY_SIZE(msg));
1295 MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
1296 }
1297 }
1298 }
1299 }
1300 else if (GetFocus() == g_pChildWnd->hTreeWnd)
1301 {
1302 if (keyPath == NULL || *keyPath == UNICODE_NULL)
1303 {
1304 MessageBeep(MB_ICONHAND);
1305 }
1306 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1307 {
1308 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1309 RefreshTreeView(g_pChildWnd->hTreeWnd);
1310 }
1311 }
1312 break;
1313 }
1314 case ID_EDIT_NEW_STRINGVALUE:
1315 CreateNewValue(hKeyRoot, keyPath, REG_SZ);
1316 break;
1317 case ID_EDIT_NEW_BINARYVALUE:
1318 CreateNewValue(hKeyRoot, keyPath, REG_BINARY);
1319 break;
1320 case ID_EDIT_NEW_DWORDVALUE:
1321 CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
1322 break;
1323 case ID_EDIT_NEW_MULTISTRINGVALUE:
1324 CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
1325 break;
1326 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
1327 CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
1328 break;
1329 case ID_EDIT_FIND:
1330 FindDialog(hWnd);
1331 break;
1332 case ID_EDIT_FINDNEXT:
1333 FindNextMessageBox(hWnd);
1334 break;
1335 case ID_EDIT_COPYKEYNAME:
1336 CopyKeyName(hWnd, hKeyRoot, keyPath);
1337 break;
1338 case ID_EDIT_PERMISSIONS:
1339 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1340 break;
1341 case ID_VIEW_REFRESH:
1342 RefreshTreeView(g_pChildWnd->hTreeWnd);
1343 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1344 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, TRUE);
1345 break;
1346 //case ID_OPTIONS_TOOLBAR:
1347 // toggle_child(hWnd, LOWORD(wParam), hToolBar);
1348 // break;
1349 case ID_EDIT_NEW_KEY:
1350 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1351 break;
1352 case ID_TREE_EXPANDBRANCH:
1353 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_EXPAND);
1354 break;
1355 case ID_TREE_COLLAPSEBRANCH:
1356 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_COLLAPSE);
1357 break;
1358 case ID_TREE_RENAME:
1359 SetFocus(g_pChildWnd->hTreeWnd);
1360 TreeView_EditLabel(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
1361 break;
1362 case ID_TREE_DELETE:
1363 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), &hKeyRoot);
1364 if (keyPath == 0 || *keyPath == 0)
1365 MessageBeep(MB_ICONHAND);
1366 else if (DeleteKey(hWnd, hKeyRoot, keyPath))
1367 DeleteNode(g_pChildWnd->hTreeWnd, 0);
1368 break;
1369 case ID_TREE_EXPORT:
1370 ExportRegistryFile(g_pChildWnd->hTreeWnd);
1371 break;
1372 case ID_TREE_PERMISSIONS:
1373 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), &hKeyRoot);
1374 RegKeyEditPermissions(hWnd, hKeyRoot, NULL, keyPath);
1375 break;
1376 case ID_SWITCH_PANELS:
1377 {
1378 BOOL bShiftDown = GetKeyState(VK_SHIFT) < 0;
1379 HWND hwndItem = GetNextDlgTabItem(g_pChildWnd->hWnd, GetFocus(), bShiftDown);
1380 if (hwndItem == g_pChildWnd->hAddressBarWnd)
1381 PostMessageW(hwndItem, EM_SETSEL, 0, -1);
1382 SetFocus(hwndItem);
1383 }
1384 break;
1385 case ID_ADDRESS_FOCUS:
1386 SendMessageW(g_pChildWnd->hAddressBarWnd, EM_SETSEL, 0, -1);
1387 SetFocus(g_pChildWnd->hAddressBarWnd);
1388 break;
1389 default:
1390 if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
1391 {
1392 HMENU hMenu;
1393 MENUITEMINFOW mii;
1394 WCHAR szFavorite[512];
1395
1396 hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
1397
1398 memset(&mii, 0, sizeof(mii));
1399 mii.cbSize = sizeof(mii);
1400 mii.fMask = MIIM_TYPE;
1401 mii.fType = MFT_STRING;
1402 mii.dwTypeData = szFavorite;
1403 mii.cch = ARRAY_SIZE(szFavorite);
1404
1405 if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
1406 {
1407 ChooseFavorite(szFavorite);
1408 }
1409 }
1410 else if ((LOWORD(wParam) >= ID_TREE_SUGGESTION_MIN) && (LOWORD(wParam) <= ID_TREE_SUGGESTION_MAX))
1411 {
1412 WORD wID = LOWORD(wParam);
1413 LPCWSTR s = Suggestions;
1414 while(wID > ID_TREE_SUGGESTION_MIN)
1415 {
1416 if (*s)
1417 s += wcslen(s) + 1;
1418 wID--;
1419 }
1420 SelectNode(g_pChildWnd->hTreeWnd, s);
1421 }
1422 else
1423 {
1424 result = FALSE;
1425 }
1426 break;
1427 }
1428
1429 if(hKey)
1430 RegCloseKey(hKey);
1431 return result;
1432 }
1433
1434 /**
1435 * PURPOSE: Processes messages for the main frame window
1436 *
1437 * WM_COMMAND - process the application menu
1438 * WM_DESTROY - post a quit message and return
1439 */
FrameWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1440 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1441 {
1442 RECT rc;
1443 switch (message)
1444 {
1445 case WM_CREATE:
1446 // For now, the Help dialog item is disabled because of lacking of HTML Help support
1447 EnableMenuItem(GetMenu(hWnd), ID_HELP_HELPTOPICS, MF_BYCOMMAND | MF_GRAYED);
1448 GetClientRect(hWnd, &rc);
1449 CreateWindowExW(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
1450 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
1451 hWnd, (HMENU)0, hInst, 0);
1452 break;
1453 case WM_COMMAND:
1454 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1455 return DefWindowProcW(hWnd, message, wParam, lParam);
1456 break;
1457 case WM_ACTIVATE:
1458 if (LOWORD(wParam) != WA_INACTIVE && g_pChildWnd)
1459 SetFocus(g_pChildWnd->hWnd);
1460 break;
1461 case WM_SIZE:
1462 resize_frame_client(hWnd);
1463 break;
1464 case WM_INITMENU:
1465 OnInitMenu(hWnd);
1466 break;
1467 case WM_ENTERMENULOOP:
1468 OnEnterMenuLoop(hWnd);
1469 break;
1470 case WM_EXITMENULOOP:
1471 OnExitMenuLoop(hWnd);
1472 break;
1473 case WM_MENUSELECT:
1474 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1475 break;
1476 case WM_SYSCOLORCHANGE:
1477 /* Forward WM_SYSCOLORCHANGE to common controls */
1478 SendMessageW(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
1479 SendMessageW(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
1480 break;
1481 case WM_DESTROY:
1482 WinHelpW(hWnd, L"regedit", HELP_QUIT, 0);
1483 SaveSettings();
1484 PostQuitMessage(0);
1485 default:
1486 return DefWindowProcW(hWnd, message, wParam, lParam);
1487 }
1488 return 0;
1489 }
1490