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