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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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