4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 /********************************************************************************
28 * Global and Local Variables:
31 #define FAVORITES_MENU_POSITION 3
33 static WCHAR s_szFavoritesRegKey
[] = L
"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
35 static BOOL bInMenuLoop
= FALSE
; /* Tells us if we are in the menu loop */
37 extern WCHAR Suggestions
[256];
38 /*******************************************************************************
39 * Local module support methods
42 static void resize_frame_rect(HWND hWnd
, PRECT prect
)
44 if (IsWindowVisible(hStatusBar
))
48 SetupStatusBar(hWnd
, TRUE
);
49 GetWindowRect(hStatusBar
, &rt
);
50 prect
->bottom
-= rt
.bottom
- rt
.top
;
52 MoveWindow(g_pChildWnd
->hWnd
, prect
->left
, prect
->top
, prect
->right
, prect
->bottom
, TRUE
);
55 static void resize_frame_client(HWND hWnd
)
59 GetClientRect(hWnd
, &rect
);
60 resize_frame_rect(hWnd
, &rect
);
63 /********************************************************************************/
65 static void OnInitMenu(HWND hWnd
)
69 DWORD dwIndex
, cbValueName
, cbValueData
, dwType
;
70 WCHAR szValueName
[256];
71 BYTE abValueData
[256];
72 static int s_nFavoriteMenuSubPos
= -1;
74 BOOL bDisplayedAny
= FALSE
;
76 /* Find Favorites menu and clear it out */
77 hMenu
= GetSubMenu(GetMenu(hWnd
), FAVORITES_MENU_POSITION
);
80 if (s_nFavoriteMenuSubPos
< 0)
82 s_nFavoriteMenuSubPos
= GetMenuItemCount(hMenu
);
86 while(RemoveMenu(hMenu
, s_nFavoriteMenuSubPos
, MF_BYPOSITION
)) ;
89 lResult
= RegOpenKeyW(HKEY_CURRENT_USER
, s_szFavoritesRegKey
, &hKey
);
90 if (lResult
!= ERROR_SUCCESS
)
96 cbValueName
= ARRAY_SIZE(szValueName
);
97 cbValueData
= sizeof(abValueData
);
98 lResult
= RegEnumValueW(hKey
, dwIndex
, szValueName
, &cbValueName
, NULL
, &dwType
, abValueData
, &cbValueData
);
99 if ((lResult
== ERROR_SUCCESS
) && (dwType
== REG_SZ
))
103 AppendMenu(hMenu
, MF_SEPARATOR
, 0, NULL
);
104 bDisplayedAny
= TRUE
;
106 AppendMenu(hMenu
, 0, ID_FAVORITES_MIN
+ GetMenuItemCount(hMenu
), szValueName
);
110 while(lResult
== ERROR_SUCCESS
);
117 static void OnEnterMenuLoop(HWND hWnd
)
120 UNREFERENCED_PARAMETER(hWnd
);
122 /* Update the status bar pane sizes */
124 SendMessageW(hStatusBar
, SB_SETPARTS
, 1, (LPARAM
)&nParts
);
126 SendMessageW(hStatusBar
, SB_SETTEXTW
, (WPARAM
)0, (LPARAM
)L
"");
129 static void OnExitMenuLoop(HWND hWnd
)
132 /* Update the status bar pane sizes*/
133 SetupStatusBar(hWnd
, TRUE
);
137 static void OnMenuSelect(HWND hWnd
, UINT nItemID
, UINT nFlags
, HMENU hSysMenu
)
142 if (nFlags
& MF_POPUP
)
144 if (hSysMenu
!= GetMenu(hWnd
))
146 if (nItemID
== 2) nItemID
= 5;
149 if (LoadStringW(hInst
, nItemID
, str
, 100))
151 /* load appropriate string*/
153 /* first newline terminates actual string*/
154 lpsz
= wcschr(lpsz
, L
'\n');
158 SendMessageW(hStatusBar
, SB_SETTEXTW
, 0, (LPARAM
)str
);
161 void SetupStatusBar(HWND hWnd
, BOOL bResize
)
165 GetClientRect(hWnd
, &rc
);
169 SendMessageW(hStatusBar
, WM_SIZE
, 0, 0);
170 SendMessageW(hStatusBar
, SB_SETPARTS
, 1, (LPARAM
)&nParts
);
173 void UpdateStatusBar(void)
176 LPCWSTR pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
178 SendMessageW(hStatusBar
, SB_SETTEXTW
, 0, (LPARAM
)pszKeyPath
);
181 static void toggle_child(HWND hWnd
, UINT cmd
, HWND hchild
)
183 BOOL vis
= IsWindowVisible(hchild
);
184 HMENU hMenuView
= GetSubMenu(hMenuFrame
, ID_VIEW_MENU
);
186 CheckMenuItem(hMenuView
, cmd
, vis
?MF_BYCOMMAND
:MF_BYCOMMAND
|MF_CHECKED
);
187 ShowWindow(hchild
, vis
?SW_HIDE
:SW_SHOW
);
188 resize_frame_client(hWnd
);
191 static BOOL
CheckCommDlgError(HWND hWnd
)
193 DWORD dwErrorCode
= CommDlgExtendedError();
194 UNREFERENCED_PARAMETER(hWnd
);
197 case CDERR_DIALOGFAILURE
:
199 case CDERR_FINDRESFAILURE
:
201 case CDERR_NOHINSTANCE
:
203 case CDERR_INITIALIZATION
:
207 case CDERR_LOCKRESFAILURE
:
209 case CDERR_NOTEMPLATE
:
211 case CDERR_LOADRESFAILURE
:
213 case CDERR_STRUCTSIZE
:
215 case CDERR_LOADSTRFAILURE
:
217 case FNERR_BUFFERTOOSMALL
:
219 case CDERR_MEMALLOCFAILURE
:
221 case FNERR_INVALIDFILENAME
:
223 case CDERR_MEMLOCKFAILURE
:
225 case FNERR_SUBCLASSFAILURE
:
233 WCHAR FileNameBuffer
[_MAX_PATH
];
234 WCHAR FileTitleBuffer
[_MAX_PATH
];
240 } FILTERPAIR
, *PFILTERPAIR
;
243 BuildFilterStrings(WCHAR
*Filter
, PFILTERPAIR Pairs
, int PairCount
)
248 for(i
= 0; i
< PairCount
; i
++)
250 c
+= LoadStringW(hInst
, Pairs
[i
].DisplayID
, &Filter
[c
], 255);
252 c
+= LoadStringW(hInst
, Pairs
[i
].FilterID
, &Filter
[c
], 255);
258 static BOOL
InitOpenFileName(HWND hWnd
, OPENFILENAME
* pofn
)
260 FILTERPAIR FilterPairs
[4];
261 static WCHAR Filter
[1024];
263 memset(pofn
, 0, sizeof(OPENFILENAME
));
264 pofn
->lStructSize
= sizeof(OPENFILENAME
);
265 pofn
->hwndOwner
= hWnd
;
266 pofn
->hInstance
= hInst
;
268 /* create filter string */
269 FilterPairs
[0].DisplayID
= IDS_FLT_REGFILES
;
270 FilterPairs
[0].FilterID
= IDS_FLT_REGFILES_FLT
;
271 FilterPairs
[1].DisplayID
= IDS_FLT_HIVFILES
;
272 FilterPairs
[1].FilterID
= IDS_FLT_HIVFILES_FLT
;
273 FilterPairs
[2].DisplayID
= IDS_FLT_REGEDIT4
;
274 FilterPairs
[2].FilterID
= IDS_FLT_REGEDIT4_FLT
;
275 FilterPairs
[3].DisplayID
= IDS_FLT_ALLFILES
;
276 FilterPairs
[3].FilterID
= IDS_FLT_ALLFILES_FLT
;
277 BuildFilterStrings(Filter
, FilterPairs
, ARRAY_SIZE(FilterPairs
));
279 pofn
->lpstrFilter
= Filter
;
280 pofn
->lpstrFile
= FileNameBuffer
;
281 pofn
->nMaxFile
= _MAX_PATH
;
282 pofn
->lpstrFileTitle
= FileTitleBuffer
;
283 pofn
->nMaxFileTitle
= _MAX_PATH
;
284 pofn
->Flags
= OFN_EXPLORER
| OFN_HIDEREADONLY
;
285 pofn
->lpstrDefExt
= L
"reg";
289 #define LOADHIVE_KEYNAMELENGTH 128
291 static INT_PTR CALLBACK
LoadHive_KeyNameInHookProc(HWND hWndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
293 static LPWSTR sKey
= NULL
;
297 sKey
= (LPWSTR
)lParam
;
300 switch(LOWORD(wParam
))
303 if(GetDlgItemTextW(hWndDlg
, IDC_EDIT_KEY
, sKey
, LOADHIVE_KEYNAMELENGTH
))
304 return EndDialog(hWndDlg
, -1);
306 return EndDialog(hWndDlg
, 0);
308 return EndDialog(hWndDlg
, 0);
315 static BOOL
EnablePrivilege(LPCWSTR lpszPrivilegeName
, LPCWSTR lpszSystemName
, BOOL bEnablePrivilege
)
318 HANDLE hToken
= NULL
;
320 if (OpenProcessToken(GetCurrentProcess(),
321 TOKEN_ADJUST_PRIVILEGES
,
326 tp
.PrivilegeCount
= 1;
327 tp
.Privileges
[0].Attributes
= (bEnablePrivilege
? SE_PRIVILEGE_ENABLED
: 0);
329 if (LookupPrivilegeValueW(lpszSystemName
,
331 &tp
.Privileges
[0].Luid
))
333 bRet
= AdjustTokenPrivileges(hToken
, FALSE
, &tp
, 0, NULL
, NULL
);
335 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED
)
345 static BOOL
LoadHive(HWND hWnd
)
350 WCHAR xPath
[LOADHIVE_KEYNAMELENGTH
];
354 /* get the item key to load the hive in */
355 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hRootKey
);
356 /* initialize the "open file" dialog */
357 InitOpenFileName(hWnd
, &ofn
);
358 /* build the "All Files" filter up */
359 filter
.DisplayID
= IDS_FLT_ALLFILES
;
360 filter
.FilterID
= IDS_FLT_ALLFILES_FLT
;
361 BuildFilterStrings(Filter
, &filter
, 1);
362 ofn
.lpstrFilter
= Filter
;
363 /* load and set the caption and flags for dialog */
364 LoadStringW(hInst
, IDS_LOAD_HIVE
, Caption
, ARRAY_SIZE(Caption
));
365 ofn
.lpstrTitle
= Caption
;
366 ofn
.Flags
|= OFN_ENABLESIZING
;
367 /* ofn.lCustData = ;*/
368 /* now load the hive */
369 if (GetOpenFileName(&ofn
))
371 if (DialogBoxParamW(hInst
, MAKEINTRESOURCEW(IDD_LOADHIVE
), hWnd
,
372 &LoadHive_KeyNameInHookProc
, (LPARAM
)xPath
))
376 /* Enable the 'restore' privilege, load the hive, disable the privilege */
377 EnablePrivilege(SE_RESTORE_NAME
, NULL
, TRUE
);
378 regLoadResult
= RegLoadKeyW(hRootKey
, xPath
, ofn
.lpstrFile
);
379 EnablePrivilege(SE_RESTORE_NAME
, NULL
, FALSE
);
381 if(regLoadResult
== ERROR_SUCCESS
)
383 /* refresh tree and list views */
384 RefreshTreeView(g_pChildWnd
->hTreeWnd
);
385 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hRootKey
);
386 RefreshListView(g_pChildWnd
->hListWnd
, hRootKey
, pszKeyPath
);
390 ErrorMessageBox(hWnd
, Caption
, regLoadResult
);
397 CheckCommDlgError(hWnd
);
402 static BOOL
UnloadHive(HWND hWnd
)
407 LONG regUnloadResult
;
409 /* get the item key to unload */
410 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hRootKey
);
411 /* load and set the caption and flags for dialog */
412 LoadStringW(hInst
, IDS_UNLOAD_HIVE
, Caption
, ARRAY_SIZE(Caption
));
414 /* Enable the 'restore' privilege, unload the hive, disable the privilege */
415 EnablePrivilege(SE_RESTORE_NAME
, NULL
, TRUE
);
416 regUnloadResult
= RegUnLoadKeyW(hRootKey
, pszKeyPath
);
417 EnablePrivilege(SE_RESTORE_NAME
, NULL
, FALSE
);
419 if(regUnloadResult
== ERROR_SUCCESS
)
421 /* refresh tree and list views */
422 RefreshTreeView(g_pChildWnd
->hTreeWnd
);
423 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hRootKey
);
424 RefreshListView(g_pChildWnd
->hListWnd
, hRootKey
, pszKeyPath
);
428 ErrorMessageBox(hWnd
, Caption
, regUnloadResult
);
434 static BOOL
ImportRegistryFile(HWND hWnd
)
438 WCHAR Caption
[128], szTitle
[512], szText
[512];
442 /* Figure out in which key path we are importing */
443 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
445 InitOpenFileName(hWnd
, &ofn
);
446 LoadStringW(hInst
, IDS_IMPORT_REG_FILE
, Caption
, ARRAY_SIZE(Caption
));
447 ofn
.lpstrTitle
= Caption
;
448 ofn
.Flags
|= OFN_ENABLESIZING
;
449 /* ofn.lCustData = ;*/
450 if (GetOpenFileName(&ofn
))
452 /* Look at the extension of the file to determine its type */
453 if (ofn
.nFileExtension
>= 1 &&
454 _wcsicmp(ofn
.lpstrFile
+ ofn
.nFileExtension
, L
"reg") == 0) /* REGEDIT4 or Windows Registry Editor Version 5.00 */
457 FILE* fp
= _wfopen(ofn
.lpstrFile
, L
"rb");
460 if (fp
== NULL
|| !import_registry_file(fp
))
462 /* Error opening the file */
463 LoadStringW(hInst
, IDS_APP_TITLE
, szTitle
, ARRAY_SIZE(szTitle
));
464 LoadStringW(hInst
, IDS_IMPORT_ERROR
, szText
, ARRAY_SIZE(szText
));
465 InfoMessageBox(hWnd
, MB_OK
| MB_ICONERROR
, szTitle
, szText
, ofn
.lpstrFile
);
470 /* Show successful import */
471 LoadStringW(hInst
, IDS_APP_TITLE
, szTitle
, ARRAY_SIZE(szTitle
));
472 LoadStringW(hInst
, IDS_IMPORT_OK
, szText
, ARRAY_SIZE(szText
));
473 InfoMessageBox(hWnd
, MB_OK
| MB_ICONINFORMATION
, szTitle
, szText
, ofn
.lpstrFile
);
480 else /* Registry Hive Files */
482 LoadStringW(hInst
, IDS_QUERY_IMPORT_HIVE_CAPTION
, szTitle
, ARRAY_SIZE(szTitle
));
483 LoadStringW(hInst
, IDS_QUERY_IMPORT_HIVE_MSG
, szText
, ARRAY_SIZE(szText
));
485 /* Display a confirmation message */
486 if (MessageBoxW(g_pChildWnd
->hWnd
, szText
, szTitle
, MB_ICONWARNING
| MB_YESNO
) == IDYES
)
491 /* Open the subkey */
492 lResult
= RegOpenKeyExW(hKeyRoot
, pszKeyPath
, 0, KEY_WRITE
, &hSubKey
);
493 if (lResult
== ERROR_SUCCESS
)
495 /* Enable the 'restore' privilege, restore the hive then disable the privilege */
496 EnablePrivilege(SE_RESTORE_NAME
, NULL
, TRUE
);
497 lResult
= RegRestoreKey(hSubKey
, ofn
.lpstrFile
, REG_FORCE_RESTORE
);
498 EnablePrivilege(SE_RESTORE_NAME
, NULL
, FALSE
);
500 /* Flush the subkey and close it */
501 RegFlushKey(hSubKey
);
502 RegCloseKey(hSubKey
);
505 /* Set the return value */
506 bRet
= (lResult
== ERROR_SUCCESS
);
508 /* Display error, if any */
509 if (!bRet
) ErrorMessageBox(hWnd
, Caption
, lResult
);
515 CheckCommDlgError(hWnd
);
518 /* refresh tree and list views */
519 RefreshTreeView(g_pChildWnd
->hTreeWnd
);
520 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
521 RefreshListView(g_pChildWnd
->hListWnd
, hKeyRoot
, pszKeyPath
);
526 static UINT_PTR CALLBACK
ExportRegistryFile_OFNHookProc(HWND hdlg
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
)
529 HWND hwndExportBranch
;
530 HWND hwndExportBranchText
;
531 UINT_PTR iResult
= 0;
533 LPWSTR pszSelectedKey
;
534 OFNOTIFY
*pOfnNotify
;
536 UNREFERENCED_PARAMETER(wParam
);
541 pOfn
= (OPENFILENAME
*) lParam
;
542 pszSelectedKey
= (LPWSTR
) pOfn
->lCustData
;
544 hwndExportAll
= GetDlgItem(hdlg
, IDC_EXPORT_ALL
);
546 SendMessageW(hwndExportAll
, BM_SETCHECK
, pszSelectedKey
? BST_UNCHECKED
: BST_CHECKED
, 0);
548 hwndExportBranch
= GetDlgItem(hdlg
, IDC_EXPORT_BRANCH
);
549 if (hwndExportBranch
)
550 SendMessageW(hwndExportBranch
, BM_SETCHECK
, pszSelectedKey
? BST_CHECKED
: BST_UNCHECKED
, 0);
552 hwndExportBranchText
= GetDlgItem(hdlg
, IDC_EXPORT_BRANCH_TEXT
);
553 if (hwndExportBranchText
)
554 SetWindowTextW(hwndExportBranchText
, pszSelectedKey
);
558 if (((NMHDR
*) lParam
)->code
== CDN_FILEOK
)
560 pOfnNotify
= (OFNOTIFY
*) lParam
;
561 pszSelectedKey
= (LPWSTR
) pOfnNotify
->lpOFN
->lCustData
;
563 hwndExportBranch
= GetDlgItem(hdlg
, IDC_EXPORT_BRANCH
);
564 hwndExportBranchText
= GetDlgItem(hdlg
, IDC_EXPORT_BRANCH_TEXT
);
565 if (hwndExportBranch
&& hwndExportBranchText
566 && (SendMessageW(hwndExportBranch
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
568 GetWindowTextW(hwndExportBranchText
, pszSelectedKey
, _MAX_PATH
);
572 pszSelectedKey
[0] = L
'\0';
580 BOOL
ExportRegistryFile(HWND hWnd
)
584 WCHAR ExportKeyPath
[_MAX_PATH
] = {0};
585 WCHAR Caption
[128], szTitle
[512], szText
[512];
589 /* Figure out which key path we are exporting */
590 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
591 GetKeyName(ExportKeyPath
, ARRAY_SIZE(ExportKeyPath
), hKeyRoot
, pszKeyPath
);
593 InitOpenFileName(hWnd
, &ofn
);
594 LoadStringW(hInst
, IDS_EXPORT_REG_FILE
, Caption
, ARRAY_SIZE(Caption
));
595 ofn
.lpstrTitle
= Caption
;
597 /* Only set the path if a key (not the root node) is selected */
600 ofn
.lCustData
= (LPARAM
) ExportKeyPath
;
602 ofn
.Flags
= OFN_ENABLETEMPLATE
| OFN_EXPLORER
| OFN_ENABLEHOOK
| OFN_OVERWRITEPROMPT
;
603 ofn
.lpfnHook
= ExportRegistryFile_OFNHookProc
;
604 ofn
.lpTemplateName
= MAKEINTRESOURCEW(IDD_EXPORTRANGE
);
605 if (GetSaveFileName(&ofn
))
607 switch (ofn
.nFilterIndex
)
609 case 2: /* Registry Hive Files */
614 /* Open the subkey */
615 lResult
= RegOpenKeyExW(hKeyRoot
, pszKeyPath
, 0, KEY_READ
, &hSubKey
);
616 if (lResult
== ERROR_SUCCESS
)
618 /* Enable the 'backup' privilege, save the hive then disable the privilege */
619 EnablePrivilege(SE_BACKUP_NAME
, NULL
, TRUE
);
620 lResult
= RegSaveKeyW(hSubKey
, ofn
.lpstrFile
, NULL
);
621 if (lResult
== ERROR_ALREADY_EXISTS
)
624 * We are here, that means that we already said "yes" to the confirmation dialog.
625 * So we absolutely want to replace the hive file.
627 if (DeleteFileW(ofn
.lpstrFile
))
630 lResult
= RegSaveKeyW(hSubKey
, ofn
.lpstrFile
, NULL
);
633 EnablePrivilege(SE_BACKUP_NAME
, NULL
, FALSE
);
635 if (lResult
!= ERROR_SUCCESS
)
638 * If we are here, it's because RegSaveKeyW has failed for any reason.
639 * The problem is that even if it has failed, it has created or
640 * replaced the exported hive file with a new empty file. We don't
641 * want to keep this file, so we delete it.
643 DeleteFileW(ofn
.lpstrFile
);
646 /* Close the subkey */
647 RegCloseKey(hSubKey
);
650 /* Set the return value */
651 bRet
= (lResult
== ERROR_SUCCESS
);
653 /* Display error, if any */
654 if (!bRet
) ErrorMessageBox(hWnd
, Caption
, lResult
);
659 case 1: /* Windows Registry Editor Version 5.00 */
660 case 3: /* REGEDIT4 */
661 default: /* All files ==> use Windows Registry Editor Version 5.00 */
663 if (!export_registry_key(ofn
.lpstrFile
, ExportKeyPath
,
664 (ofn
.nFilterIndex
== 3 ? REG_FORMAT_4
667 /* Error creating the file */
668 LoadStringW(hInst
, IDS_APP_TITLE
, szTitle
, ARRAY_SIZE(szTitle
));
669 LoadStringW(hInst
, IDS_EXPORT_ERROR
, szText
, ARRAY_SIZE(szText
));
670 InfoMessageBox(hWnd
, MB_OK
| MB_ICONERROR
, szTitle
, szText
, ofn
.lpstrFile
);
684 CheckCommDlgError(hWnd
);
690 BOOL
PrintRegistryHive(HWND hWnd
, LPWSTR path
)
694 UNREFERENCED_PARAMETER(path
);
696 ZeroMemory(&pd
, sizeof(PRINTDLG
));
697 pd
.lStructSize
= sizeof(PRINTDLG
);
699 pd
.hDevMode
= NULL
; /* Don't forget to free or store hDevMode*/
700 pd
.hDevNames
= NULL
; /* Don't forget to free or store hDevNames*/
701 pd
.Flags
= PD_USEDEVMODECOPIESANDCOLLATE
| PD_RETURNDC
;
703 pd
.nFromPage
= 0xFFFF;
706 pd
.nMaxPage
= 0xFFFF;
709 /* GDI calls to render output. */
710 DeleteDC(pd
.hDC
); /* Delete DC when done.*/
716 hResult
= PrintDlgEx(&pd
);
719 switch (pd
.dwResultAction
)
721 case PD_RESULT_APPLY
:
722 /*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. */
724 case PD_RESULT_CANCEL
:
725 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
727 case PD_RESULT_PRINT
:
728 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
739 /*Insufficient memory. */
742 /* One or more arguments are invalid. */
745 /*Invalid pointer. */
751 /*Unspecified error. */
762 static void ChooseFavorite(LPCWSTR pszFavorite
)
765 WCHAR szFavoritePath
[512];
766 DWORD cbData
, dwType
;
768 if (RegOpenKeyExW(HKEY_CURRENT_USER
, s_szFavoritesRegKey
, 0, KEY_QUERY_VALUE
, &hKey
) != ERROR_SUCCESS
)
771 cbData
= sizeof(szFavoritePath
);
772 memset(szFavoritePath
, 0, sizeof(szFavoritePath
));
773 if (RegQueryValueExW(hKey
, pszFavorite
, NULL
, &dwType
, (LPBYTE
) szFavoritePath
, &cbData
) != ERROR_SUCCESS
)
776 if (dwType
== REG_SZ
)
777 SelectNode(g_pChildWnd
->hTreeWnd
, szFavoritePath
);
784 BOOL
CopyKeyName(HWND hWnd
, HKEY hRootKey
, LPCWSTR keyName
)
786 BOOL bClipboardOpened
= FALSE
;
787 BOOL bSuccess
= FALSE
;
792 if (!OpenClipboard(hWnd
))
794 bClipboardOpened
= TRUE
;
796 if (!EmptyClipboard())
799 if (!GetKeyName(szBuffer
, ARRAY_SIZE(szBuffer
), hRootKey
, keyName
))
802 hGlobal
= GlobalAlloc(GMEM_MOVEABLE
, (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
806 s
= GlobalLock(hGlobal
);
808 GlobalUnlock(hGlobal
);
810 SetClipboardData(CF_UNICODETEXT
, hGlobal
);
814 if (bClipboardOpened
)
819 static BOOL
CreateNewValue(HKEY hRootKey
, LPCWSTR pszKeyPath
, DWORD dwType
)
821 WCHAR szNewValueFormat
[128];
822 WCHAR szNewValue
[128];
825 DWORD dwExistingType
, cbData
;
830 if (RegOpenKeyExW(hRootKey
, pszKeyPath
, 0, KEY_QUERY_VALUE
| KEY_SET_VALUE
,
831 &hKey
) != ERROR_SUCCESS
)
834 LoadStringW(hInst
, IDS_NEW_VALUE
, szNewValueFormat
, ARRAY_SIZE(szNewValueFormat
));
838 wsprintf(szNewValue
, szNewValueFormat
, iIndex
++);
839 cbData
= sizeof(data
);
840 lResult
= RegQueryValueExW(hKey
, szNewValue
, NULL
, &dwExistingType
, data
, &cbData
);
842 while(lResult
== ERROR_SUCCESS
);
847 cbData
= sizeof(DWORD
);
851 cbData
= sizeof(WCHAR
);
855 * WARNING: An empty multi-string has only one null char.
856 * Indeed, multi-strings are built in the following form:
857 * str1\0str2\0...strN\0\0
858 * where each strI\0 is a null-terminated string, and it
859 * ends with a terminating empty string.
860 * Therefore an empty multi-string contains only the terminating
861 * empty string, that is, one null char.
863 cbData
= sizeof(WCHAR
);
865 case REG_QWORD
: /* REG_QWORD_LITTLE_ENDIAN */
866 cbData
= sizeof(DWORDLONG
); // == sizeof(DWORD) * 2;
872 memset(data
, 0, cbData
);
873 lResult
= RegSetValueExW(hKey
, szNewValue
, 0, dwType
, data
, cbData
);
875 if (lResult
!= ERROR_SUCCESS
)
880 RefreshListView(g_pChildWnd
->hListWnd
, hRootKey
, pszKeyPath
);
882 /* locate the newly added value, and get ready to rename it */
883 memset(&lvfi
, 0, sizeof(lvfi
));
884 lvfi
.flags
= LVFI_STRING
;
885 lvfi
.psz
= szNewValue
;
886 iIndex
= ListView_FindItem(g_pChildWnd
->hListWnd
, -1, &lvfi
);
888 (void)ListView_EditLabel(g_pChildWnd
->hListWnd
, iIndex
);
894 InitializeRemoteRegistryPicker(OUT IDsObjectPicker
**pDsObjectPicker
)
898 *pDsObjectPicker
= NULL
;
900 hRet
= CoCreateInstance(&CLSID_DsObjectPicker
,
902 CLSCTX_INPROC_SERVER
,
903 &IID_IDsObjectPicker
,
904 (LPVOID
*)pDsObjectPicker
);
907 DSOP_INIT_INFO InitInfo
;
908 static DSOP_SCOPE_INIT_INFO Scopes
[] =
911 sizeof(DSOP_SCOPE_INIT_INFO
),
912 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE
| DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE
|
913 DSOP_SCOPE_TYPE_GLOBAL_CATALOG
| DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN
|
914 DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN
| DSOP_SCOPE_TYPE_WORKGROUP
|
915 DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
| DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN
,
919 DSOP_FILTER_COMPUTERS
,
923 DSOP_DOWNLEVEL_FILTER_COMPUTERS
931 InitInfo
.cbSize
= sizeof(InitInfo
);
932 InitInfo
.pwzTargetComputer
= NULL
;
933 InitInfo
.cDsScopeInfos
= ARRAY_SIZE(Scopes
);
934 InitInfo
.aDsScopeInfos
= Scopes
;
935 InitInfo
.flOptions
= 0;
936 InitInfo
.cAttributesToFetch
= 0;
937 InitInfo
.apwzAttributeNames
= NULL
;
939 hRet
= (*pDsObjectPicker
)->lpVtbl
->Initialize(*pDsObjectPicker
,
944 /* delete the object picker in case initialization failed! */
945 (*pDsObjectPicker
)->lpVtbl
->Release(*pDsObjectPicker
);
953 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker
*pDsObjectPicker
,
954 IN HWND hwndParent OPTIONAL
,
958 IDataObject
*pdo
= NULL
;
961 hRet
= pDsObjectPicker
->lpVtbl
->InvokeDialog(pDsObjectPicker
,
969 fe
.cfFormat
= (CLIPFORMAT
) RegisterClipboardFormatW(CFSTR_DSOP_DS_SELECTION_LIST
);
971 fe
.dwAspect
= DVASPECT_CONTENT
;
973 fe
.tymed
= TYMED_HGLOBAL
;
975 hRet
= pdo
->lpVtbl
->GetData(pdo
,
980 PDS_SELECTION_LIST SelectionList
= (PDS_SELECTION_LIST
)GlobalLock(stm
.hGlobal
);
981 if (SelectionList
!= NULL
)
983 if (SelectionList
->cItems
== 1)
985 size_t nlen
= wcslen(SelectionList
->aDsSelection
[0].pwzName
);
992 SelectionList
->aDsSelection
[0].pwzName
,
993 nlen
* sizeof(WCHAR
));
995 lpBuffer
[nlen
] = L
'\0';
998 GlobalUnlock(stm
.hGlobal
);
1001 ReleaseStgMedium(&stm
);
1004 pdo
->lpVtbl
->Release(pdo
);
1011 FreeObjectPicker(IN IDsObjectPicker
*pDsObjectPicker
)
1013 pDsObjectPicker
->lpVtbl
->Release(pDsObjectPicker
);
1016 /*******************************************************************************
1018 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
1020 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
1023 static BOOL
_CmdWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1025 HKEY hKeyRoot
= 0, hKey
= 0;
1029 REGSAM regsam
= KEY_READ
;
1032 UNREFERENCED_PARAMETER(lParam
);
1033 UNREFERENCED_PARAMETER(message
);
1035 switch (LOWORD(wParam
))
1037 case ID_REGISTRY_LOADHIVE
:
1040 case ID_REGISTRY_UNLOADHIVE
:
1043 case ID_REGISTRY_IMPORTREGISTRYFILE
:
1044 ImportRegistryFile(hWnd
);
1046 case ID_REGISTRY_EXPORTREGISTRYFILE
:
1047 ExportRegistryFile(hWnd
);
1049 case ID_REGISTRY_CONNECTNETWORKREGISTRY
:
1051 IDsObjectPicker
*ObjectPicker
;
1052 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1055 hRet
= CoInitialize(NULL
);
1056 if (SUCCEEDED(hRet
))
1058 hRet
= InitializeRemoteRegistryPicker(&ObjectPicker
);
1059 if (SUCCEEDED(hRet
))
1061 hRet
= InvokeRemoteRegistryPickerDialog(ObjectPicker
,
1064 ARRAY_SIZE(szComputerName
));
1067 /* FIXME - connect to the registry */
1070 FreeObjectPicker(ObjectPicker
);
1078 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY
:
1080 case ID_REGISTRY_PRINT
:
1081 PrintRegistryHive(hWnd
, L
"");
1083 case ID_REGISTRY_EXIT
:
1084 DestroyWindow(hWnd
);
1086 case ID_VIEW_STATUSBAR
:
1087 toggle_child(hWnd
, LOWORD(wParam
), hStatusBar
);
1089 case ID_HELP_HELPTOPICS
:
1090 WinHelpW(hWnd
, L
"regedit", HELP_FINDER
, 0);
1099 GetClientRect(g_pChildWnd
->hWnd
, &rt
);
1100 pt
.x
= rt
.left
+ g_pChildWnd
->nSplitPos
;
1101 pt
.y
= (rt
.bottom
/ 2);
1103 if(ClientToScreen(g_pChildWnd
->hWnd
, &pts
))
1105 SetCursorPos(pts
.x
, pts
.y
);
1106 SetCursor(LoadCursorW(0, IDC_SIZEWE
));
1107 SendMessageW(g_pChildWnd
->hWnd
, WM_LBUTTONDOWN
, 0, MAKELPARAM(pt
.x
, pt
.y
));
1111 case ID_EDIT_RENAME
:
1112 case ID_EDIT_MODIFY
:
1113 case ID_EDIT_MODIFY_BIN
:
1114 case ID_EDIT_DELETE
:
1115 regsam
|= KEY_WRITE
;
1119 keyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
1120 valueName
= GetValueName(g_pChildWnd
->hListWnd
, -1);
1123 if (RegOpenKeyExW(hKeyRoot
, keyPath
, 0, regsam
, &hKey
) != ERROR_SUCCESS
)
1127 switch (LOWORD(wParam
))
1129 case ID_EDIT_MODIFY
:
1130 if (valueName
&& ModifyValue(hWnd
, hKey
, valueName
, FALSE
))
1131 RefreshListView(g_pChildWnd
->hListWnd
, hKeyRoot
, keyPath
);
1133 case ID_EDIT_MODIFY_BIN
:
1134 if (valueName
&& ModifyValue(hWnd
, hKey
, valueName
, TRUE
))
1135 RefreshListView(g_pChildWnd
->hListWnd
, hKeyRoot
, keyPath
);
1137 case ID_EDIT_RENAME
:
1138 if (GetFocus() == g_pChildWnd
->hListWnd
)
1140 if(ListView_GetSelectedCount(g_pChildWnd
->hListWnd
) == 1)
1142 item
= ListView_GetNextItem(g_pChildWnd
->hListWnd
, -1, LVNI_SELECTED
);
1145 (void)ListView_EditLabel(g_pChildWnd
->hListWnd
, item
);
1149 else if (GetFocus() == g_pChildWnd
->hTreeWnd
)
1151 /* Get focused entry of treeview (if any) */
1152 HTREEITEM hItem
= TreeView_GetSelection(g_pChildWnd
->hTreeWnd
);
1154 (void)TreeView_EditLabel(g_pChildWnd
->hTreeWnd
, hItem
);
1157 case ID_EDIT_DELETE
:
1159 if (GetFocus() == g_pChildWnd
->hListWnd
&& hKey
)
1161 UINT nSelected
= ListView_GetSelectedCount(g_pChildWnd
->hListWnd
);
1164 WCHAR msg
[128], caption
[128];
1165 LoadStringW(hInst
, IDS_QUERY_DELETE_CONFIRM
, caption
, ARRAY_SIZE(caption
));
1166 LoadStringW(hInst
, (nSelected
== 1 ? IDS_QUERY_DELETE_ONE
: IDS_QUERY_DELETE_MORE
), msg
, ARRAY_SIZE(msg
));
1167 if(MessageBoxW(g_pChildWnd
->hWnd
, msg
, caption
, MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
1173 while((ni
= ListView_GetNextItem(g_pChildWnd
->hListWnd
, item
, LVNI_SELECTED
)) > -1)
1175 valueName
= GetValueName(g_pChildWnd
->hListWnd
, item
);
1176 if(RegDeleteValueW(hKey
, valueName
) != ERROR_SUCCESS
)
1183 RefreshListView(g_pChildWnd
->hListWnd
, hKeyRoot
, keyPath
);
1186 LoadStringW(hInst
, IDS_ERR_DELVAL_CAPTION
, caption
, ARRAY_SIZE(caption
));
1187 LoadStringW(hInst
, IDS_ERR_DELETEVALUE
, msg
, ARRAY_SIZE(msg
));
1188 MessageBoxW(g_pChildWnd
->hWnd
, msg
, caption
, MB_ICONSTOP
);
1193 else if (GetFocus() == g_pChildWnd
->hTreeWnd
)
1195 if (keyPath
== NULL
|| *keyPath
== UNICODE_NULL
)
1197 MessageBeep(MB_ICONHAND
);
1199 else if (DeleteKey(hWnd
, hKeyRoot
, keyPath
))
1201 DeleteNode(g_pChildWnd
->hTreeWnd
, 0);
1202 RefreshTreeView(g_pChildWnd
->hTreeWnd
);
1207 case ID_EDIT_NEW_STRINGVALUE
:
1208 CreateNewValue(hKeyRoot
, keyPath
, REG_SZ
);
1210 case ID_EDIT_NEW_BINARYVALUE
:
1211 CreateNewValue(hKeyRoot
, keyPath
, REG_BINARY
);
1213 case ID_EDIT_NEW_DWORDVALUE
:
1214 CreateNewValue(hKeyRoot
, keyPath
, REG_DWORD
);
1216 case ID_EDIT_NEW_MULTISTRINGVALUE
:
1217 CreateNewValue(hKeyRoot
, keyPath
, REG_MULTI_SZ
);
1219 case ID_EDIT_NEW_EXPANDABLESTRINGVALUE
:
1220 CreateNewValue(hKeyRoot
, keyPath
, REG_EXPAND_SZ
);
1225 case ID_EDIT_FINDNEXT
:
1226 FindNextMessageBox(hWnd
);
1228 case ID_EDIT_COPYKEYNAME
:
1229 CopyKeyName(hWnd
, hKeyRoot
, keyPath
);
1231 case ID_EDIT_PERMISSIONS
:
1232 RegKeyEditPermissions(hWnd
, hKeyRoot
, NULL
, keyPath
);
1234 case ID_REGISTRY_PRINTERSETUP
:
1237 /*PAGESETUPDLG psd;*/
1238 /*PageSetupDlg(&psd);*/
1240 case ID_REGISTRY_OPENLOCAL
:
1243 case ID_VIEW_REFRESH
:
1244 RefreshTreeView(g_pChildWnd
->hTreeWnd
);
1245 keyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
1246 RefreshListView(g_pChildWnd
->hListWnd
, hKeyRoot
, keyPath
);
1248 /*case ID_OPTIONS_TOOLBAR:*/
1249 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1251 case ID_EDIT_NEW_KEY
:
1252 CreateNewKey(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
));
1255 case ID_TREE_EXPANDBRANCH
:
1256 TreeView_Expand(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
), TVE_EXPAND
);
1258 case ID_TREE_COLLAPSEBRANCH
:
1259 TreeView_Expand(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
), TVE_COLLAPSE
);
1261 case ID_TREE_RENAME
:
1262 SetFocus(g_pChildWnd
->hTreeWnd
);
1263 TreeView_EditLabel(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
));
1265 case ID_TREE_DELETE
:
1266 keyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
), &hKeyRoot
);
1267 if (keyPath
== 0 || *keyPath
== 0)
1269 MessageBeep(MB_ICONHAND
);
1271 else if (DeleteKey(hWnd
, hKeyRoot
, keyPath
))
1272 DeleteNode(g_pChildWnd
->hTreeWnd
, 0);
1274 case ID_TREE_EXPORT
:
1275 ExportRegistryFile(g_pChildWnd
->hTreeWnd
);
1277 case ID_TREE_PERMISSIONS
:
1278 keyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, TreeView_GetSelection(g_pChildWnd
->hTreeWnd
), &hKeyRoot
);
1279 RegKeyEditPermissions(hWnd
, hKeyRoot
, NULL
, keyPath
);
1281 case ID_SWITCH_PANELS
:
1283 BOOL bShiftDown
= GetKeyState(VK_SHIFT
) < 0;
1284 HWND hwndItem
= GetNextDlgTabItem(g_pChildWnd
->hWnd
, GetFocus(), bShiftDown
);
1285 if (hwndItem
== g_pChildWnd
->hAddressBarWnd
)
1286 PostMessageW(hwndItem
, EM_SETSEL
, 0, -1);
1291 case ID_ADDRESS_FOCUS
:
1292 SendMessageW(g_pChildWnd
->hAddressBarWnd
, EM_SETSEL
, 0, -1);
1293 SetFocus(g_pChildWnd
->hAddressBarWnd
);
1297 if ((LOWORD(wParam
) >= ID_FAVORITES_MIN
) && (LOWORD(wParam
) <= ID_FAVORITES_MAX
))
1301 WCHAR szFavorite
[512];
1303 hMenu
= GetSubMenu(GetMenu(hWnd
), FAVORITES_MENU_POSITION
);
1305 memset(&mii
, 0, sizeof(mii
));
1306 mii
.cbSize
= sizeof(mii
);
1307 mii
.fMask
= MIIM_TYPE
;
1308 mii
.fType
= MFT_STRING
;
1309 mii
.dwTypeData
= szFavorite
;
1310 mii
.cch
= ARRAY_SIZE(szFavorite
);
1312 if (GetMenuItemInfo(hMenu
, LOWORD(wParam
) - ID_FAVORITES_MIN
, TRUE
, &mii
))
1314 ChooseFavorite(szFavorite
);
1317 else if ((LOWORD(wParam
) >= ID_TREE_SUGGESTION_MIN
) && (LOWORD(wParam
) <= ID_TREE_SUGGESTION_MAX
))
1319 WORD wID
= LOWORD(wParam
);
1320 LPCWSTR s
= Suggestions
;
1321 while(wID
> ID_TREE_SUGGESTION_MIN
)
1327 SelectNode(g_pChildWnd
->hTreeWnd
, s
);
1341 /********************************************************************************
1343 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1345 * PURPOSE: Processes messages for the main frame window.
1347 * WM_COMMAND - process the application menu
1348 * WM_DESTROY - post a quit message and return
1352 LRESULT CALLBACK
FrameWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1358 // For now, the Help dialog item is disabled because of lacking of HTML Help support
1359 EnableMenuItem(GetMenu(hWnd
), ID_HELP_HELPTOPICS
, MF_BYCOMMAND
| MF_GRAYED
);
1360 GetClientRect(hWnd
, &rc
);
1361 CreateWindowExW(0, szChildClass
, NULL
, WS_CHILD
| WS_VISIBLE
,
1362 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
1363 hWnd
, (HMENU
)0, hInst
, 0);
1366 if (!_CmdWndProc(hWnd
, message
, wParam
, lParam
))
1367 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
1370 if (LOWORD(hWnd
) && g_pChildWnd
)
1371 SetFocus(g_pChildWnd
->hWnd
);
1374 resize_frame_client(hWnd
);
1381 case WM_ENTERMENULOOP
:
1382 OnEnterMenuLoop(hWnd
);
1384 case WM_EXITMENULOOP
:
1385 OnExitMenuLoop(hWnd
);
1388 OnMenuSelect(hWnd
, LOWORD(wParam
), HIWORD(wParam
), (HMENU
)lParam
);
1390 case WM_SYSCOLORCHANGE
:
1391 /* Forward WM_SYSCOLORCHANGE to common controls */
1392 SendMessageW(g_pChildWnd
->hListWnd
, WM_SYSCOLORCHANGE
, 0, 0);
1393 SendMessageW(g_pChildWnd
->hTreeWnd
, WM_SYSCOLORCHANGE
, 0, 0);
1396 WinHelpW(hWnd
, L
"regedit", HELP_QUIT
, 0);
1400 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);