1 /* 2 * Open With Context Menu extension 3 * 4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org> 5 * Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL (fprop); 25 26 /// Folder Options: 27 /// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF} 28 /// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210 29 /// Verbs: Open / RunAs 30 /// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0 31 32 /// ShellFolder Attributes: 0x0 33 34 typedef struct 35 { 36 WCHAR FileExtension[30]; 37 WCHAR FileDescription[100]; 38 WCHAR ClassKey[MAX_PATH]; 39 WCHAR ClassName[64]; 40 DWORD EditFlags; 41 WCHAR AppName[64]; 42 HICON hIconLarge; 43 HICON hIconSmall; 44 WCHAR ProgramPath[MAX_PATH]; 45 WCHAR IconPath[MAX_PATH]; 46 INT nIconIndex; 47 } FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY; 48 49 // uniquely-defined icon entry for Advanced Settings 50 typedef struct ADVANCED_ICON 51 { 52 WCHAR szPath[MAX_PATH]; 53 UINT nIconIndex; 54 } ADVANCED_ICON; 55 56 // predefined icon IDs (See CreateTreeImageList function below) 57 #define I_CHECKED 0 58 #define I_UNCHECKED 1 59 #define I_CHECKED_DISABLED 2 60 #define I_UNCHECKED_DISABLED 3 61 #define I_RADIO_CHECKED 4 62 #define I_RADIO_UNCHECKED 5 63 #define I_RADIO_CHECKED_DISABLED 6 64 #define I_RADIO_UNCHECKED_DISABLED 7 65 66 #define PREDEFINED_ICON_COUNT 8 67 68 // definition of icon stock 69 static ADVANCED_ICON * s_AdvancedIcons = NULL; 70 static INT s_AdvancedIconCount = 0; 71 static HIMAGELIST s_hImageList = NULL; 72 73 static INT 74 Advanced_FindIcon(LPCWSTR pszPath, UINT nIconIndex) 75 { 76 for (INT i = PREDEFINED_ICON_COUNT; i < s_AdvancedIconCount; ++i) 77 { 78 ADVANCED_ICON *pIcon = &s_AdvancedIcons[i]; 79 if (pIcon->nIconIndex == nIconIndex && 80 lstrcmpiW(pIcon->szPath, pszPath) == 0) 81 { 82 return i; // icon ID 83 } 84 } 85 return -1; // not found 86 } 87 88 static INT 89 Advanced_AddIcon(LPCWSTR pszPath, UINT nIconIndex) 90 { 91 ADVANCED_ICON *pAllocated; 92 93 // return the ID if already existed 94 INT nIconID = Advanced_FindIcon(pszPath, nIconIndex); 95 if (nIconID != -1) 96 return nIconID; // already exists 97 98 // extract a small icon 99 HICON hIconSmall = NULL; 100 ExtractIconExW(pszPath, nIconIndex, NULL, &hIconSmall, 1); 101 if (hIconSmall == NULL) 102 return -1; // failure 103 104 // resize s_AdvancedIcons 105 size_t Size = (s_AdvancedIconCount + 1) * sizeof(ADVANCED_ICON); 106 pAllocated = (ADVANCED_ICON *)realloc(s_AdvancedIcons, Size); 107 if (pAllocated == NULL) 108 return -1; // failure 109 else 110 s_AdvancedIcons = pAllocated; 111 112 // save icon information 113 ADVANCED_ICON *pIcon = &s_AdvancedIcons[s_AdvancedIconCount]; 114 lstrcpynW(pIcon->szPath, pszPath, _countof(pIcon->szPath)); 115 pIcon->nIconIndex = nIconIndex; 116 117 // add the icon to the image list 118 ImageList_AddIcon(s_hImageList, hIconSmall); 119 120 // increment the counter 121 nIconID = s_AdvancedIconCount; 122 ++s_AdvancedIconCount; 123 124 DestroyIcon(hIconSmall); 125 126 return nIconID; // newly-added icon ID 127 } 128 129 // types of Advanced Setting entry 130 typedef enum ADVANCED_ENTRY_TYPE 131 { 132 AETYPE_GROUP, 133 AETYPE_CHECKBOX, 134 AETYPE_RADIO, 135 } ADVANCED_ENTRY_TYPE; 136 137 // an entry info of Advanced Settings 138 typedef struct ADVANCED_ENTRY 139 { 140 DWORD dwID; // entry ID 141 DWORD dwParentID; // parent entry ID 142 DWORD dwResourceID; // resource ID 143 WCHAR szKeyName[64]; // entry key name 144 DWORD dwType; // ADVANCED_ENTRY_TYPE 145 WCHAR szText[MAX_PATH]; // text 146 INT nIconID; // icon ID (See ADVANCED_ICON) 147 148 HKEY hkeyRoot; // registry root key 149 WCHAR szRegPath[MAX_PATH]; // registry path 150 WCHAR szValueName[64]; // registry value name 151 152 DWORD dwCheckedValue; // checked value 153 DWORD dwUncheckedValue; // unchecked value 154 DWORD dwDefaultValue; // defalut value 155 BOOL bHasUncheckedValue; // If FALSE, UncheckedValue is invalid 156 157 HTREEITEM hItem; // for TreeView 158 BOOL bGrayed; // disabled? 159 BOOL bChecked; // checked? 160 } ADVANCED_ENTRY, *PADVANCED_ENTRY; 161 162 // definition of advanced entries 163 static ADVANCED_ENTRY * s_Advanced = NULL; 164 static INT s_AdvancedCount = 0; 165 166 static HBITMAP 167 Create24BppBitmap(HDC hDC, INT cx, INT cy) 168 { 169 BITMAPINFO bi; 170 LPVOID pvBits; 171 172 ZeroMemory(&bi, sizeof(bi)); 173 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 174 bi.bmiHeader.biWidth = cx; 175 bi.bmiHeader.biHeight = cy; 176 bi.bmiHeader.biPlanes = 1; 177 bi.bmiHeader.biBitCount = 24; 178 bi.bmiHeader.biCompression = BI_RGB; 179 180 HBITMAP hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0); 181 return hbm; 182 } 183 184 static HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) 185 { 186 HDC hDC = CreateCompatibleDC(NULL); 187 if (!hDC) 188 return NULL; 189 190 HBITMAP hbm = Create24BppBitmap(hDC, cx, cy); 191 if (!hbm) 192 { 193 DeleteDC(hDC); 194 return NULL; 195 } 196 197 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 198 { 199 RECT rc = { 0, 0, cx, cy }; 200 FillRect(hDC, &rc, HBRUSH(COLOR_3DFACE + 1)); 201 if (hIcon) 202 { 203 DrawIconEx(hDC, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL); 204 } 205 } 206 SelectObject(hDC, hbmOld); 207 DeleteDC(hDC); 208 209 return hbm; 210 } 211 212 static HBITMAP 213 CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) 214 { 215 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 216 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 217 218 HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); 219 if (hbm == NULL) 220 return NULL; // failure 221 222 RECT Rect, BoxRect; 223 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 224 BoxRect = Rect; 225 InflateRect(&BoxRect, -1, -1); 226 227 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 228 { 229 UINT uState = DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_MONO; 230 if (bCheck) 231 uState |= DFCS_CHECKED; 232 if (!bEnabled) 233 uState |= DFCS_INACTIVE; 234 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 235 } 236 SelectObject(hDC, hbmOld); 237 238 return hbm; // success 239 } 240 241 static HBITMAP 242 CreateCheckMask(HDC hDC) 243 { 244 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 245 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 246 247 HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); 248 if (hbm == NULL) 249 return NULL; // failure 250 251 RECT Rect, BoxRect; 252 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 253 BoxRect = Rect; 254 InflateRect(&BoxRect, -1, -1); 255 256 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 257 { 258 FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); 259 FillRect(hDC, &BoxRect, HBRUSH(GetStockObject(BLACK_BRUSH))); 260 } 261 SelectObject(hDC, hbmOld); 262 263 return hbm; // success 264 } 265 266 static HBITMAP 267 CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) 268 { 269 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 270 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 271 272 HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); 273 if (hbm == NULL) 274 return NULL; // failure 275 276 RECT Rect, BoxRect; 277 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 278 BoxRect = Rect; 279 InflateRect(&BoxRect, -1, -1); 280 281 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 282 { 283 UINT uState = DFCS_BUTTONRADIOIMAGE | DFCS_FLAT | DFCS_MONO; 284 if (bCheck) 285 uState |= DFCS_CHECKED; 286 if (!bEnabled) 287 uState |= DFCS_INACTIVE; 288 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 289 } 290 SelectObject(hDC, hbmOld); 291 292 return hbm; // success 293 } 294 295 static HBITMAP 296 CreateRadioMask(HDC hDC) 297 { 298 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 299 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 300 301 HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); 302 if (hbm == NULL) 303 return NULL; // failure 304 305 RECT Rect, BoxRect; 306 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 307 BoxRect = Rect; 308 InflateRect(&BoxRect, -1, -1); 309 310 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 311 { 312 FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); 313 UINT uState = DFCS_BUTTONRADIOMASK | DFCS_FLAT | DFCS_MONO; 314 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 315 } 316 SelectObject(hDC, hbmOld); 317 318 return hbm; // success 319 } 320 321 static HIMAGELIST 322 CreateTreeImageList(VOID) 323 { 324 HIMAGELIST hImageList; 325 hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 9, 1); 326 if (hImageList == NULL) 327 return NULL; // failure 328 329 // free if existed 330 if (s_AdvancedIcons) 331 { 332 free(s_AdvancedIcons); 333 s_AdvancedIcons = NULL; 334 } 335 s_AdvancedIconCount = 0; 336 337 // allocate now 338 ADVANCED_ICON *pAllocated; 339 size_t Size = PREDEFINED_ICON_COUNT * sizeof(ADVANCED_ICON); 340 pAllocated = (ADVANCED_ICON *)calloc(1, Size); 341 if (pAllocated == NULL) 342 return NULL; // failure 343 344 s_AdvancedIconCount = PREDEFINED_ICON_COUNT; 345 s_AdvancedIcons = pAllocated; 346 347 // add the predefined icons 348 349 HDC hDC = CreateCompatibleDC(NULL); 350 HBITMAP hbmMask = CreateCheckMask(hDC); 351 352 HBITMAP hbmChecked, hbmUnchecked; 353 354 hbmChecked = CreateCheckImage(hDC, TRUE); 355 ImageList_Add(hImageList, hbmChecked, hbmMask); 356 DeleteObject(hbmChecked); 357 358 hbmUnchecked = CreateCheckImage(hDC, FALSE); 359 ImageList_Add(hImageList, hbmUnchecked, hbmMask); 360 DeleteObject(hbmUnchecked); 361 362 hbmChecked = CreateCheckImage(hDC, TRUE, FALSE); 363 ImageList_Add(hImageList, hbmChecked, hbmMask); 364 DeleteObject(hbmChecked); 365 366 hbmUnchecked = CreateCheckImage(hDC, FALSE, FALSE); 367 ImageList_Add(hImageList, hbmUnchecked, hbmMask); 368 DeleteObject(hbmUnchecked); 369 370 DeleteObject(hbmMask); 371 hbmMask = CreateRadioMask(hDC); 372 373 hbmChecked = CreateRadioImage(hDC, TRUE); 374 ImageList_Add(hImageList, hbmChecked, hbmMask); 375 DeleteObject(hbmChecked); 376 377 hbmUnchecked = CreateRadioImage(hDC, FALSE); 378 ImageList_Add(hImageList, hbmUnchecked, hbmMask); 379 DeleteObject(hbmUnchecked); 380 381 hbmChecked = CreateRadioImage(hDC, TRUE, FALSE); 382 ImageList_Add(hImageList, hbmChecked, hbmMask); 383 DeleteObject(hbmChecked); 384 385 hbmUnchecked = CreateRadioImage(hDC, FALSE, FALSE); 386 ImageList_Add(hImageList, hbmUnchecked, hbmMask); 387 DeleteObject(hbmUnchecked); 388 389 DeleteObject(hbmMask); 390 391 return hImageList; 392 } 393 394 static ADVANCED_ENTRY * 395 Advanced_GetItem(DWORD dwID) 396 { 397 if (dwID == DWORD(-1)) 398 return NULL; 399 400 for (INT i = 0; i < s_AdvancedCount; ++i) 401 { 402 ADVANCED_ENTRY *pEntry = &s_Advanced[i]; 403 if (pEntry->dwID == dwID) 404 return pEntry; 405 } 406 return NULL; // failure 407 } 408 409 static INT 410 Advanced_GetImage(ADVANCED_ENTRY *pEntry) 411 { 412 switch (pEntry->dwType) 413 { 414 case AETYPE_GROUP: 415 return pEntry->nIconID; 416 417 case AETYPE_CHECKBOX: 418 if (pEntry->bGrayed) 419 { 420 if (pEntry->bChecked) 421 return I_CHECKED_DISABLED; 422 else 423 return I_UNCHECKED_DISABLED; 424 } 425 else 426 { 427 if (pEntry->bChecked) 428 return I_CHECKED; 429 else 430 return I_UNCHECKED; 431 } 432 433 case AETYPE_RADIO: 434 if (pEntry->bGrayed) 435 { 436 if (pEntry->bChecked) 437 return I_RADIO_CHECKED_DISABLED; 438 else 439 return I_RADIO_UNCHECKED_DISABLED; 440 } 441 else 442 { 443 if (pEntry->bChecked) 444 return I_RADIO_CHECKED; 445 else 446 return I_RADIO_UNCHECKED; 447 } 448 } 449 return -1; // failure 450 } 451 452 static VOID 453 Advanced_InsertEntry(HWND hwndTreeView, ADVANCED_ENTRY *pEntry) 454 { 455 ADVANCED_ENTRY *pParent = Advanced_GetItem(pEntry->dwParentID); 456 HTREEITEM hParent = TVI_ROOT; 457 if (pParent) 458 hParent = pParent->hItem; 459 460 TV_INSERTSTRUCT Insertion; 461 ZeroMemory(&Insertion, sizeof(Insertion)); 462 Insertion.hParent = hParent; 463 Insertion.hInsertAfter = TVI_LAST; 464 Insertion.item.mask = 465 TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; 466 Insertion.item.pszText = pEntry->szText; 467 468 INT iImage = Advanced_GetImage(pEntry); 469 Insertion.item.iImage = Insertion.item.iSelectedImage = iImage; 470 Insertion.item.lParam = pEntry->dwID; 471 pEntry->hItem = TreeView_InsertItem(hwndTreeView, &Insertion); 472 } 473 474 static VOID 475 Advanced_InsertAll(HWND hwndTreeView) 476 { 477 TreeView_DeleteAllItems(hwndTreeView); 478 479 // insert the entries 480 ADVANCED_ENTRY *pEntry; 481 for (INT i = 0; i < s_AdvancedCount; ++i) 482 { 483 pEntry = &s_Advanced[i]; 484 Advanced_InsertEntry(hwndTreeView, pEntry); 485 } 486 487 // expand all 488 for (INT i = 0; i < s_AdvancedCount; ++i) 489 { 490 pEntry = &s_Advanced[i]; 491 if (pEntry->dwType == AETYPE_GROUP) 492 { 493 TreeView_Expand(hwndTreeView, pEntry->hItem, TVE_EXPAND); 494 } 495 } 496 } 497 498 static BOOL 499 Advanced_LoadTree(HKEY hKey, LPCWSTR pszKeyName, DWORD dwParentID) 500 { 501 DWORD dwIndex; 502 WCHAR szKeyName[64], szText[MAX_PATH], *pch; 503 DWORD Size, Value; 504 ADVANCED_ENTRY *pAllocated; 505 506 // resize s_Advanced 507 Size = (s_AdvancedCount + 1) * sizeof(ADVANCED_ENTRY); 508 pAllocated = (ADVANCED_ENTRY *)realloc(s_Advanced, Size); 509 if (pAllocated == NULL) 510 return FALSE; // failure 511 else 512 s_Advanced = pAllocated; 513 514 ADVANCED_ENTRY *pEntry = &s_Advanced[s_AdvancedCount]; 515 516 // dwID, dwParentID, szKeyName 517 pEntry->dwID = s_AdvancedCount; 518 pEntry->dwParentID = dwParentID; 519 lstrcpynW(pEntry->szKeyName, pszKeyName, _countof(pEntry->szKeyName)); 520 521 // Text, ResourceID 522 pEntry->szText[0] = 0; 523 pEntry->dwResourceID = 0; 524 szText[0] = 0; 525 Size = sizeof(szText); 526 RegQueryValueExW(hKey, L"Text", NULL, NULL, LPBYTE(szText), &Size); 527 if (szText[0] == L'@') 528 { 529 pch = wcsrchr(szText, L','); 530 if (pch) 531 { 532 *pch = 0; 533 dwIndex = abs(_wtoi(pch + 1)); 534 pEntry->dwResourceID = dwIndex; 535 } 536 HINSTANCE hInst = LoadLibraryW(&szText[1]); 537 LoadStringW(hInst, dwIndex, szText, _countof(szText)); 538 FreeLibrary(hInst); 539 } 540 else 541 { 542 pEntry->dwResourceID = DWORD(-1); 543 } 544 lstrcpynW(pEntry->szText, szText, _countof(pEntry->szText)); 545 546 // Type 547 szText[0] = 0; 548 RegQueryValueExW(hKey, L"Type", NULL, NULL, LPBYTE(szText), &Size); 549 if (lstrcmpiW(szText, L"checkbox") == 0) 550 pEntry->dwType = AETYPE_CHECKBOX; 551 else if (lstrcmpiW(szText, L"radio") == 0) 552 pEntry->dwType = AETYPE_RADIO; 553 else if (lstrcmpiW(szText, L"group") == 0) 554 pEntry->dwType = AETYPE_GROUP; 555 else 556 return FALSE; // failure 557 558 pEntry->nIconID = -1; 559 if (pEntry->dwType == AETYPE_GROUP) 560 { 561 // Bitmap (Icon) 562 UINT nIconIndex = 0; 563 Size = sizeof(szText); 564 szText[0] = 0; 565 RegQueryValueExW(hKey, L"Bitmap", NULL, NULL, LPBYTE(szText), &Size); 566 567 WCHAR szExpanded[MAX_PATH]; 568 ExpandEnvironmentStringsW(szText, szExpanded, _countof(szExpanded)); 569 pch = wcsrchr(szExpanded, L','); 570 if (pch) 571 { 572 *pch = 0; 573 nIconIndex = abs(_wtoi(pch + 1)); 574 } 575 pEntry->nIconID = Advanced_AddIcon(szExpanded, nIconIndex); 576 } 577 578 if (pEntry->dwType == AETYPE_GROUP) 579 { 580 pEntry->hkeyRoot = NULL; 581 pEntry->szRegPath[0] = 0; 582 pEntry->szValueName[0] = 0; 583 pEntry->dwCheckedValue = 0; 584 pEntry->bHasUncheckedValue = FALSE; 585 pEntry->dwUncheckedValue = 0; 586 pEntry->dwDefaultValue = 0; 587 pEntry->hItem = NULL; 588 pEntry->bGrayed = FALSE; 589 pEntry->bChecked = FALSE; 590 } 591 else 592 { 593 // HKeyRoot 594 Value = DWORD(HKEY_CURRENT_USER); 595 Size = sizeof(Value); 596 RegQueryValueExW(hKey, L"HKeyRoot", NULL, NULL, LPBYTE(&Value), &Size); 597 pEntry->hkeyRoot = HKEY(Value); 598 599 // RegPath 600 pEntry->szRegPath[0] = 0; 601 Size = sizeof(szText); 602 RegQueryValueExW(hKey, L"RegPath", NULL, NULL, LPBYTE(szText), &Size); 603 lstrcpynW(pEntry->szRegPath, szText, _countof(pEntry->szRegPath)); 604 605 // ValueName 606 pEntry->szValueName[0] = 0; 607 Size = sizeof(szText); 608 RegQueryValueExW(hKey, L"ValueName", NULL, NULL, LPBYTE(szText), &Size); 609 lstrcpynW(pEntry->szValueName, szText, _countof(pEntry->szValueName)); 610 611 // CheckedValue 612 Size = sizeof(Value); 613 Value = 0x00000001; 614 RegQueryValueExW(hKey, L"CheckedValue", NULL, NULL, LPBYTE(&Value), &Size); 615 pEntry->dwCheckedValue = Value; 616 617 // UncheckedValue 618 Size = sizeof(Value); 619 Value = 0x00000000; 620 pEntry->bHasUncheckedValue = TRUE; 621 if (RegQueryValueExW(hKey, L"UncheckedValue", NULL, 622 NULL, LPBYTE(&Value), &Size) != ERROR_SUCCESS) 623 { 624 pEntry->bHasUncheckedValue = FALSE; 625 } 626 pEntry->dwUncheckedValue = Value; 627 628 // DefaultValue 629 Size = sizeof(Value); 630 Value = 0x00000001; 631 RegQueryValueExW(hKey, L"DefaultValue", NULL, NULL, LPBYTE(&Value), &Size); 632 pEntry->dwDefaultValue = Value; 633 634 // hItem 635 pEntry->hItem = NULL; 636 637 // bGrayed, bChecked 638 HKEY hkeyTarget; 639 Value = pEntry->dwDefaultValue; 640 pEntry->bGrayed = TRUE; 641 if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0, 642 KEY_READ, &hkeyTarget) == ERROR_SUCCESS) 643 { 644 Size = sizeof(Value); 645 if (RegQueryValueExW(hkeyTarget, pEntry->szValueName, NULL, NULL, 646 LPBYTE(&Value), &Size) == ERROR_SUCCESS) 647 { 648 pEntry->bGrayed = FALSE; 649 } 650 RegCloseKey(hkeyTarget); 651 } 652 pEntry->bChecked = (Value == pEntry->dwCheckedValue); 653 } 654 655 // Grayed (ReactOS extension) 656 Size = sizeof(Value); 657 Value = FALSE; 658 RegQueryValueExW(hKey, L"Grayed", NULL, NULL, LPBYTE(&Value), &Size); 659 if (!pEntry->bGrayed) 660 pEntry->bGrayed = Value; 661 662 BOOL bIsGroup = (pEntry->dwType == AETYPE_GROUP); 663 dwParentID = pEntry->dwID; 664 ++s_AdvancedCount; 665 666 if (!bIsGroup) 667 return TRUE; // success 668 669 // load the children 670 dwIndex = 0; 671 while (RegEnumKeyW(hKey, dwIndex, szKeyName, 672 _countof(szKeyName)) == ERROR_SUCCESS) 673 { 674 HKEY hkeyChild; 675 if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ, 676 &hkeyChild) != ERROR_SUCCESS) 677 { 678 ++dwIndex; 679 continue; // failure 680 } 681 682 Advanced_LoadTree(hkeyChild, szKeyName, dwParentID); 683 RegCloseKey(hkeyChild); 684 685 ++dwIndex; 686 } 687 688 return TRUE; // success 689 } 690 691 static BOOL 692 Advanced_LoadAll(VOID) 693 { 694 static const WCHAR s_szAdvanced[] = 695 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"; 696 697 // free if already existed 698 if (s_Advanced) 699 { 700 free(s_Advanced); 701 s_Advanced = NULL; 702 } 703 s_AdvancedCount = 0; 704 705 HKEY hKey; 706 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szAdvanced, 0, 707 KEY_READ, &hKey) != ERROR_SUCCESS) 708 { 709 return FALSE; // failure 710 } 711 712 // load the children 713 WCHAR szKeyName[64]; 714 DWORD dwIndex = 0; 715 while (RegEnumKeyW(hKey, dwIndex, szKeyName, 716 _countof(szKeyName)) == ERROR_SUCCESS) 717 { 718 HKEY hkeyChild; 719 if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ, 720 &hkeyChild) != ERROR_SUCCESS) 721 { 722 ++dwIndex; 723 continue; // failure 724 } 725 726 Advanced_LoadTree(hkeyChild, szKeyName, DWORD(-1)); 727 RegCloseKey(hkeyChild); 728 729 ++dwIndex; 730 } 731 732 RegCloseKey(hKey); 733 734 return TRUE; // success 735 } 736 737 static int 738 Advanced_Compare(const void *x, const void *y) 739 { 740 ADVANCED_ENTRY *pEntry1 = (ADVANCED_ENTRY *)x; 741 ADVANCED_ENTRY *pEntry2 = (ADVANCED_ENTRY *)y; 742 743 DWORD dwParentID1 = pEntry1->dwParentID; 744 DWORD dwParentID2 = pEntry2->dwParentID; 745 746 if (dwParentID1 == dwParentID2) 747 return lstrcmpi(pEntry1->szText, pEntry2->szText); 748 749 DWORD i, m, n; 750 const UINT MAX_DEPTH = 32; 751 ADVANCED_ENTRY *pArray1[MAX_DEPTH]; 752 ADVANCED_ENTRY *pArray2[MAX_DEPTH]; 753 754 // Make ancestor lists 755 for (i = m = n = 0; i < MAX_DEPTH; ++i) 756 { 757 ADVANCED_ENTRY *pParent1 = Advanced_GetItem(dwParentID1); 758 ADVANCED_ENTRY *pParent2 = Advanced_GetItem(dwParentID2); 759 if (!pParent1 && !pParent2) 760 break; 761 762 if (pParent1) 763 { 764 pArray1[m++] = pParent1; 765 dwParentID1 = pParent1->dwParentID; 766 } 767 if (pParent2) 768 { 769 pArray2[n++] = pParent2; 770 dwParentID2 = pParent2->dwParentID; 771 } 772 } 773 774 UINT k = min(m, n); 775 for (i = 0; i < k; ++i) 776 { 777 INT nCompare = lstrcmpi(pArray1[m - i - 1]->szText, pArray2[n - i - 1]->szText); 778 if (nCompare < 0) 779 return -1; 780 if (nCompare > 0) 781 return 1; 782 } 783 784 if (m < n) 785 return -1; 786 if (m > n) 787 return 1; 788 return lstrcmpi(pEntry1->szText, pEntry2->szText); 789 } 790 791 static VOID 792 Advanced_SortAll(VOID) 793 { 794 qsort(s_Advanced, s_AdvancedCount, sizeof(ADVANCED_ENTRY), Advanced_Compare); 795 } 796 797 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj); 798 799 static VOID 800 UpdateGeneralIcons(HWND hDlg) 801 { 802 HWND hwndTaskIcon, hwndFolderIcon, hwndClickIcon; 803 HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL; 804 LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL; 805 806 // show task setting icon 807 if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED) 808 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS); 809 else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED) 810 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS); 811 812 if (lpTaskIconName) 813 { 814 hTaskIcon = (HICON)LoadImage(shell32_hInstance, 815 lpTaskIconName, 816 IMAGE_ICON, 817 0, 818 0, 819 LR_DEFAULTCOLOR); 820 if (hTaskIcon) 821 { 822 hwndTaskIcon = GetDlgItem(hDlg, 823 IDC_FOLDER_OPTIONS_TASKICON); 824 if (hwndTaskIcon) 825 { 826 SendMessage(hwndTaskIcon, 827 STM_SETIMAGE, 828 IMAGE_ICON, 829 (LPARAM)hTaskIcon); 830 } 831 } 832 } 833 834 // show Folder setting icons 835 if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED) 836 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW); 837 else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED) 838 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW); 839 840 if (lpFolderIconName) 841 { 842 hFolderIcon = (HICON)LoadImage(shell32_hInstance, 843 lpFolderIconName, 844 IMAGE_ICON, 845 0, 846 0, 847 LR_DEFAULTCOLOR); 848 if (hFolderIcon) 849 { 850 hwndFolderIcon = GetDlgItem(hDlg, 851 IDC_FOLDER_OPTIONS_FOLDERICON); 852 if (hwndFolderIcon) 853 { 854 SendMessage(hwndFolderIcon, 855 STM_SETIMAGE, 856 IMAGE_ICON, 857 (LPARAM)hFolderIcon); 858 } 859 } 860 } 861 862 // Show click setting icon 863 if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED) 864 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN); 865 else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED) 866 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN); 867 868 if (lpClickIconName) 869 { 870 hClickIcon = (HICON)LoadImage(shell32_hInstance, 871 lpClickIconName, 872 IMAGE_ICON, 873 0, 874 0, 875 LR_DEFAULTCOLOR); 876 if (hClickIcon) 877 { 878 hwndClickIcon = GetDlgItem(hDlg, 879 IDC_FOLDER_OPTIONS_CLICKICON); 880 if (hwndClickIcon) 881 { 882 SendMessage(hwndClickIcon, 883 STM_SETIMAGE, 884 IMAGE_ICON, 885 (LPARAM)hClickIcon); 886 } 887 } 888 } 889 890 // Clean up 891 if(hTaskIcon) 892 DeleteObject(hTaskIcon); 893 if(hFolderIcon) 894 DeleteObject(hFolderIcon); 895 if(hClickIcon) 896 DeleteObject(hClickIcon); 897 898 return; 899 } 900 901 INT_PTR 902 CALLBACK 903 FolderOptionsGeneralDlg( 904 HWND hwndDlg, 905 UINT uMsg, 906 WPARAM wParam, 907 LPARAM lParam 908 ) 909 { 910 switch(uMsg) 911 { 912 case WM_INITDIALOG: 913 // FIXME 914 break; 915 916 case WM_COMMAND: 917 switch (LOWORD(wParam)) 918 { 919 case IDC_FOLDER_OPTIONS_COMMONTASKS: 920 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS: 921 case IDC_FOLDER_OPTIONS_SAMEWINDOW: 922 case IDC_FOLDER_OPTIONS_OWNWINDOW: 923 case IDC_FOLDER_OPTIONS_SINGLECLICK: 924 case IDC_FOLDER_OPTIONS_DOUBLECLICK: 925 if (HIWORD(wParam) == BN_CLICKED) 926 { 927 UpdateGeneralIcons(hwndDlg); 928 929 /* Enable the 'Apply' button */ 930 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 931 } 932 break; 933 } 934 break; 935 936 case WM_NOTIFY: 937 { 938 LPNMHDR pnmh = (LPNMHDR)lParam; 939 940 switch (pnmh->code) 941 { 942 case PSN_SETACTIVE: 943 break; 944 945 case PSN_APPLY: 946 break; 947 } 948 break; 949 } 950 951 case WM_DESTROY: 952 break; 953 954 default: 955 return FALSE; 956 } 957 return FALSE; 958 } 959 960 static BOOL 961 ViewDlg_OnInitDialog(HWND hwndDlg) 962 { 963 HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); 964 965 s_hImageList = CreateTreeImageList(); 966 TreeView_SetImageList(hwndTreeView, s_hImageList, TVSIL_NORMAL); 967 968 Advanced_LoadAll(); 969 Advanced_SortAll(); 970 Advanced_InsertAll(hwndTreeView); 971 972 return TRUE; // set focus 973 } 974 975 static BOOL 976 ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem) 977 { 978 HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); 979 980 // get the item 981 TV_ITEM Item; 982 INT i; 983 ZeroMemory(&Item, sizeof(Item)); 984 Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM; 985 Item.hItem = hItem; 986 if (!TreeView_GetItem(hwndTreeView, &Item)) 987 return FALSE; // no such item 988 989 ADVANCED_ENTRY *pEntry = Advanced_GetItem(Item.lParam); 990 if (pEntry == NULL) 991 return FALSE; // no such item 992 if (pEntry->bGrayed) 993 return FALSE; // disabled 994 995 // toggle check mark 996 Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; 997 switch (pEntry->dwType) 998 { 999 case AETYPE_CHECKBOX: 1000 pEntry->bChecked = !pEntry->bChecked; 1001 break; 1002 1003 case AETYPE_RADIO: 1004 // reset all the entries of the same parent 1005 for (i = 0; i < s_AdvancedCount; ++i) 1006 { 1007 ADVANCED_ENTRY *pEntry2 = &s_Advanced[i]; 1008 if (pEntry->dwParentID == pEntry2->dwParentID) 1009 { 1010 pEntry2->bChecked = FALSE; 1011 1012 Item.hItem = pEntry2->hItem; 1013 INT iImage = Advanced_GetImage(pEntry2); 1014 Item.iImage = Item.iSelectedImage = iImage; 1015 TreeView_SetItem(hwndTreeView, &Item); 1016 } 1017 } 1018 pEntry->bChecked = TRUE; 1019 break; 1020 1021 default: 1022 return FALSE; // failure 1023 } 1024 Item.iImage = Item.iSelectedImage = Advanced_GetImage(pEntry); 1025 Item.hItem = hItem; 1026 TreeView_SetItem(hwndTreeView, &Item); 1027 1028 // redraw the item 1029 RECT rcItem; 1030 TreeView_GetItemRect(hwndTreeView, hItem, &rcItem, FALSE); 1031 InvalidateRect(hwndTreeView, &rcItem, TRUE); 1032 return TRUE; // success 1033 } 1034 1035 static VOID 1036 ViewDlg_OnTreeViewClick(HWND hwndDlg) 1037 { 1038 HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); 1039 1040 // do hit test to get the clicked item 1041 TV_HITTESTINFO HitTest; 1042 ZeroMemory(&HitTest, sizeof(HitTest)); 1043 DWORD dwPos = GetMessagePos(); 1044 HitTest.pt.x = LOWORD(dwPos); 1045 HitTest.pt.y = HIWORD(dwPos); 1046 ScreenToClient(hwndTreeView, &HitTest.pt); 1047 HTREEITEM hItem = TreeView_HitTest(hwndTreeView, &HitTest); 1048 1049 // toggle the check mark if possible 1050 if (ViewDlg_ToggleCheckItem(hwndDlg, hItem)) 1051 { 1052 // property sheet was changed 1053 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1054 } 1055 } 1056 1057 static void 1058 ViewDlg_OnTreeViewKeyDown(HWND hwndDlg, TV_KEYDOWN *KeyDown) 1059 { 1060 HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); 1061 1062 if (KeyDown->wVKey == VK_SPACE) 1063 { 1064 // [Space] key was pressed 1065 HTREEITEM hItem = TreeView_GetSelection(hwndTreeView); 1066 if (ViewDlg_ToggleCheckItem(hwndDlg, hItem)) 1067 { 1068 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1069 } 1070 } 1071 } 1072 1073 static INT_PTR 1074 ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw) 1075 { 1076 NMCUSTOMDRAW& nmcd = Draw->nmcd; 1077 switch (nmcd.dwDrawStage) 1078 { 1079 case CDDS_PREPAINT: 1080 return CDRF_NOTIFYITEMDRAW; // for CDDS_ITEMPREPAINT 1081 1082 case CDDS_ITEMPREPAINT: 1083 if (!(nmcd.uItemState & CDIS_SELECTED)) // not selected 1084 { 1085 LPARAM lParam = nmcd.lItemlParam; 1086 ADVANCED_ENTRY *pEntry = Advanced_GetItem(lParam); 1087 if (pEntry && pEntry->bGrayed) // disabled 1088 { 1089 // draw as grayed 1090 Draw->clrText = GetSysColor(COLOR_GRAYTEXT); 1091 Draw->clrTextBk = GetSysColor(COLOR_WINDOW); 1092 return CDRF_NEWFONT; 1093 } 1094 } 1095 break; 1096 1097 default: 1098 break; 1099 } 1100 return CDRF_DODEFAULT; 1101 } 1102 1103 static VOID 1104 Advanced_RestoreDefaults(HWND hwndDlg) 1105 { 1106 HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); 1107 1108 for (INT i = 0; i < s_AdvancedCount; ++i) 1109 { 1110 // ignore if the type is group 1111 ADVANCED_ENTRY *pEntry = &s_Advanced[i]; 1112 if (pEntry->dwType == AETYPE_GROUP) 1113 continue; 1114 1115 // set default value on registry 1116 HKEY hKey; 1117 if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 1118 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) 1119 { 1120 continue; 1121 } 1122 RegSetValueExW(hKey, pEntry->szValueName, 0, REG_DWORD, 1123 LPBYTE(pEntry->dwDefaultValue), sizeof(DWORD)); 1124 RegCloseKey(hKey); 1125 1126 // update check status 1127 pEntry->bChecked = (pEntry->dwCheckedValue == pEntry->dwDefaultValue); 1128 1129 // update the image 1130 TV_ITEM Item; 1131 ZeroMemory(&Item, sizeof(Item)); 1132 Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; 1133 Item.hItem = pEntry->hItem; 1134 Item.iImage = Item.iSelectedImage = Advanced_GetImage(pEntry); 1135 TreeView_SetItem(hwndTreeView, &Item); 1136 } 1137 1138 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 1139 } 1140 1141 /* FIXME: These macros should not be defined here */ 1142 #ifndef SSF_SHOWSUPERHIDDEN 1143 #define SSF_SHOWSUPERHIDDEN 0x00040000 1144 #endif 1145 #ifndef SSF_SEPPROCESS 1146 #define SSF_SEPPROCESS 0x00080000 1147 #endif 1148 1149 static VOID 1150 ScanAdvancedSettings(SHELLSTATE *pSS, DWORD *pdwMask) 1151 { 1152 for (INT i = 0; i < s_AdvancedCount; ++i) 1153 { 1154 const ADVANCED_ENTRY *pEntry = &s_Advanced[i]; 1155 if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed) 1156 continue; 1157 1158 BOOL bChecked = pEntry->bChecked; 1159 1160 // FIXME: Add more items 1161 if (lstrcmpiW(pEntry->szKeyName, L"SuperHidden") == 0) 1162 { 1163 pSS->fShowSuperHidden = !bChecked ? 1 : 0; 1164 *pdwMask |= SSF_SHOWSUPERHIDDEN; 1165 continue; 1166 } 1167 if (lstrcmpiW(pEntry->szKeyName, L"DesktopProcess") == 0) 1168 { 1169 pSS->fSepProcess = bChecked ? 1 : 0; 1170 *pdwMask |= SSF_SEPPROCESS; 1171 continue; 1172 } 1173 if (lstrcmpiW(pEntry->szKeyName, L"SHOWALL") == 0) 1174 { 1175 pSS->fShowAllObjects = !bChecked ? 1 : 0; 1176 *pdwMask |= SSF_SHOWALLOBJECTS; 1177 continue; 1178 } 1179 if (lstrcmpiW(pEntry->szKeyName, L"HideFileExt") == 0) 1180 { 1181 pSS->fShowExtensions = !bChecked ? 1 : 0; 1182 *pdwMask |= SSF_SHOWEXTENSIONS; 1183 continue; 1184 } 1185 if (lstrcmpiW(pEntry->szKeyName, L"ShowCompColor") == 0) 1186 { 1187 pSS->fShowCompColor = bChecked ? 1 : 0; 1188 *pdwMask |= SSF_SHOWCOMPCOLOR; 1189 continue; 1190 } 1191 if (lstrcmpiW(pEntry->szKeyName, L"ShowInfoTip") == 0) 1192 { 1193 pSS->fShowInfoTip = bChecked ? 1 : 0; 1194 *pdwMask |= SSF_SHOWINFOTIP; 1195 continue; 1196 } 1197 } 1198 } 1199 1200 extern "C" 1201 VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet); 1202 1203 static BOOL CALLBACK RefreshBrowsersCallback (HWND hWnd, LPARAM msg) 1204 { 1205 WCHAR ClassName[100]; 1206 if (GetClassName(hWnd, ClassName, 100)) 1207 { 1208 if (!wcscmp(ClassName, L"Progman") || 1209 !wcscmp(ClassName, L"CabinetWClass") || 1210 !wcscmp(ClassName, L"ExploreWClass")) 1211 { 1212 PostMessage(hWnd, WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0); 1213 } 1214 } 1215 return TRUE; 1216 } 1217 1218 static VOID 1219 ViewDlg_Apply(HWND hwndDlg) 1220 { 1221 for (INT i = 0; i < s_AdvancedCount; ++i) 1222 { 1223 // ignore the entry if the type is group or the entry is grayed 1224 ADVANCED_ENTRY *pEntry = &s_Advanced[i]; 1225 if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed) 1226 continue; 1227 1228 // open the registry key 1229 HKEY hkeyTarget; 1230 if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0, 1231 KEY_WRITE, &hkeyTarget) != ERROR_SUCCESS) 1232 { 1233 continue; 1234 } 1235 1236 // checked or unchecked? 1237 DWORD dwValue, dwSize; 1238 if (pEntry->bChecked) 1239 { 1240 dwValue = pEntry->dwCheckedValue; 1241 } 1242 else 1243 { 1244 if (pEntry->bHasUncheckedValue) 1245 { 1246 dwValue = pEntry->dwUncheckedValue; 1247 } 1248 else 1249 { 1250 // there is no unchecked value 1251 RegCloseKey(hkeyTarget); 1252 continue; // ignore 1253 } 1254 } 1255 1256 // set the value 1257 dwSize = sizeof(dwValue); 1258 RegSetValueExW(hkeyTarget, pEntry->szValueName, 0, REG_DWORD, 1259 LPBYTE(&dwValue), dwSize); 1260 1261 // close now 1262 RegCloseKey(hkeyTarget); 1263 } 1264 1265 // scan advanced settings for user's settings 1266 DWORD dwMask = 0; 1267 SHELLSTATE ShellState; 1268 ZeroMemory(&ShellState, sizeof(ShellState)); 1269 ScanAdvancedSettings(&ShellState, &dwMask); 1270 1271 // update user's settings 1272 SHGetSetSettings(&ShellState, dwMask, TRUE); 1273 1274 // notify all 1275 SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0); 1276 1277 EnumWindows(RefreshBrowsersCallback, NULL); 1278 } 1279 1280 INT_PTR CALLBACK 1281 FolderOptionsViewDlg( 1282 HWND hwndDlg, 1283 UINT uMsg, 1284 WPARAM wParam, 1285 LPARAM lParam) 1286 { 1287 INT_PTR Result; 1288 NMTVCUSTOMDRAW *Draw; 1289 1290 switch(uMsg) 1291 { 1292 case WM_INITDIALOG: 1293 return ViewDlg_OnInitDialog(hwndDlg); 1294 1295 case WM_COMMAND: 1296 switch (LOWORD(wParam)) 1297 { 1298 case 14004: // Restore Defaults 1299 Advanced_RestoreDefaults(hwndDlg); 1300 break; 1301 } 1302 break; 1303 1304 case WM_NOTIFY: 1305 switch (LPNMHDR(lParam)->code) 1306 { 1307 case NM_CLICK: // clicked on treeview 1308 ViewDlg_OnTreeViewClick(hwndDlg); 1309 break; 1310 1311 case NM_CUSTOMDRAW: // custom draw (for graying) 1312 Draw = (NMTVCUSTOMDRAW *)lParam; 1313 Result = ViewDlg_OnTreeCustomDraw(hwndDlg, Draw); 1314 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, Result); 1315 return Result; 1316 1317 case TVN_KEYDOWN: // key is down 1318 ViewDlg_OnTreeViewKeyDown(hwndDlg, (TV_KEYDOWN *)lParam); 1319 break; 1320 1321 case PSN_APPLY: // [Apply] is clicked 1322 ViewDlg_Apply(hwndDlg); 1323 break; 1324 1325 default: 1326 break; 1327 } 1328 break; 1329 } 1330 1331 return FALSE; 1332 } 1333 1334 static 1335 VOID 1336 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl) 1337 { 1338 RECT clientRect; 1339 LVCOLUMNW col; 1340 WCHAR szName[50]; 1341 DWORD dwStyle; 1342 int columnSize = 140; 1343 1344 1345 if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR))) 1346 { 1347 /* default to english */ 1348 wcscpy(szName, L"Extensions"); 1349 } 1350 1351 /* make sure its null terminated */ 1352 szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0; 1353 1354 GetClientRect(hDlgCtrl, &clientRect); 1355 ZeroMemory(&col, sizeof(LV_COLUMN)); 1356 columnSize = 140; //FIXME 1357 col.iSubItem = 0; 1358 col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT; 1359 col.fmt = LVCFMT_FIXED_WIDTH; 1360 col.cx = columnSize | LVCFMT_LEFT; 1361 col.cchTextMax = wcslen(szName); 1362 col.pszText = szName; 1363 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&col); 1364 1365 if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR))) 1366 { 1367 /* default to english */ 1368 wcscpy(szName, L"File Types"); 1369 ERR("Failed to load localized string!\n"); 1370 } 1371 1372 col.iSubItem = 1; 1373 col.cx = clientRect.right - clientRect.left - columnSize; 1374 col.cchTextMax = wcslen(szName); 1375 col.pszText = szName; 1376 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&col); 1377 1378 /* set full select style */ 1379 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 1380 dwStyle = dwStyle | LVS_EX_FULLROWSELECT; 1381 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); 1382 } 1383 1384 static BOOL 1385 DeleteExt(HWND hwndDlg, LPCWSTR pszExt) 1386 { 1387 if (*pszExt != L'.') 1388 return FALSE; 1389 1390 // open ".ext" key 1391 HKEY hKey; 1392 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pszExt, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 1393 return FALSE; 1394 1395 // query "extfile" key name 1396 WCHAR szValue[64] = { 0 }; 1397 DWORD cbValue = sizeof(szValue); 1398 RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(szValue), &cbValue); 1399 RegCloseKey(hKey); 1400 1401 // delete "extfile" key (if any) 1402 if (szValue[0]) 1403 SHDeleteKeyW(HKEY_CLASSES_ROOT, szValue); 1404 1405 // delete ".ext" key 1406 return SHDeleteKeyW(HKEY_CLASSES_ROOT, pszExt) == ERROR_SUCCESS; 1407 } 1408 1409 static inline HICON 1410 DoExtractIcon(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconPath, 1411 INT iIndex = 0, BOOL bSmall = FALSE) 1412 { 1413 HICON hIcon = NULL; 1414 1415 if (iIndex < 0) 1416 { 1417 // A negative value will be interpreted as a negated resource ID. 1418 iIndex = -iIndex; 1419 1420 INT cx, cy; 1421 HINSTANCE hDLL = LoadLibraryExW(IconPath, NULL, LOAD_LIBRARY_AS_DATAFILE); 1422 if (bSmall) 1423 { 1424 cx = GetSystemMetrics(SM_CXSMICON); 1425 cy = GetSystemMetrics(SM_CYSMICON); 1426 } 1427 else 1428 { 1429 cx = GetSystemMetrics(SM_CXICON); 1430 cy = GetSystemMetrics(SM_CYICON); 1431 } 1432 hIcon = HICON(LoadImageW(hDLL, MAKEINTRESOURCEW(iIndex), IMAGE_ICON, 1433 cx, cy, 0)); 1434 FreeLibrary(hDLL); 1435 } 1436 else 1437 { 1438 // A positive value is icon index. 1439 if (bSmall) 1440 ExtractIconExW(IconPath, iIndex, NULL, &hIcon, 1); 1441 else 1442 ExtractIconExW(IconPath, iIndex, &hIcon, NULL, 1); 1443 } 1444 return hIcon; 1445 } 1446 1447 static void 1448 DoFileTypeIconLocation(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) 1449 { 1450 // Expand the REG_EXPAND_SZ string by environment variables 1451 WCHAR szLocation[MAX_PATH + 32]; 1452 if (!ExpandEnvironmentStringsW(IconLocation, szLocation, _countof(szLocation))) 1453 { 1454 return; 1455 } 1456 1457 Entry->nIconIndex = PathParseIconLocationW(szLocation); 1458 StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), szLocation); 1459 Entry->hIconLarge = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, FALSE); 1460 Entry->hIconSmall = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, TRUE); 1461 } 1462 1463 static BOOL 1464 GetFileTypeIconsEx(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) 1465 { 1466 Entry->hIconLarge = Entry->hIconSmall = NULL; 1467 1468 if (lstrcmpiW(Entry->FileExtension, L".exe") == 0 || 1469 lstrcmpiW(Entry->FileExtension, L".scr") == 0) 1470 { 1471 // It's an executable 1472 Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE)); 1473 Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE), IMAGE_ICON, 1474 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); 1475 StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), L"%SystemRoot%\\system32\\shell32.dll"); 1476 Entry->nIconIndex = -IDI_SHELL_EXE; 1477 } 1478 else if (lstrcmpW(IconLocation, L"%1") == 0) 1479 { 1480 return FALSE; // self icon 1481 } 1482 else 1483 { 1484 DoFileTypeIconLocation(Entry, IconLocation); 1485 } 1486 1487 return Entry->hIconLarge && Entry->hIconSmall; 1488 } 1489 1490 static BOOL 1491 GetFileTypeIconsByKey(HKEY hKey, PFOLDER_FILE_TYPE_ENTRY Entry) 1492 { 1493 Entry->hIconLarge = Entry->hIconSmall = NULL; 1494 1495 // Open the "DefaultIcon" registry key 1496 HKEY hDefIconKey; 1497 LONG nResult = RegOpenKeyExW(hKey, L"DefaultIcon", 0, KEY_READ, &hDefIconKey); 1498 if (nResult != ERROR_SUCCESS) 1499 return FALSE; 1500 1501 // Get the icon location 1502 WCHAR szLocation[MAX_PATH + 32] = { 0 }; 1503 DWORD dwSize = sizeof(szLocation); 1504 nResult = RegQueryValueExW(hDefIconKey, NULL, NULL, NULL, LPBYTE(szLocation), &dwSize); 1505 1506 RegCloseKey(hDefIconKey); 1507 1508 if (nResult != ERROR_SUCCESS || szLocation[0] == 0) 1509 return FALSE; 1510 1511 return GetFileTypeIconsEx(Entry, szLocation); 1512 } 1513 1514 static BOOL 1515 QueryFileDescription(LPCWSTR ProgramPath, LPWSTR pszName, INT cchName) 1516 { 1517 SHFILEINFOW FileInfo = { 0 }; 1518 if (SHGetFileInfoW(ProgramPath, 0, &FileInfo, sizeof(FileInfo), SHGFI_DISPLAYNAME)) 1519 { 1520 StringCchCopyW(pszName, cchName, FileInfo.szDisplayName); 1521 return TRUE; 1522 } 1523 1524 return !!GetFileTitleW(ProgramPath, pszName, cchName); 1525 } 1526 1527 static void 1528 SetFileTypeEntryDefaultIcon(PFOLDER_FILE_TYPE_ENTRY Entry) 1529 { 1530 Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS)); 1531 INT cxSmall = GetSystemMetrics(SM_CXSMICON); 1532 INT cySmall = GetSystemMetrics(SM_CYSMICON); 1533 Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS), 1534 IMAGE_ICON, cxSmall, cySmall, 0)); 1535 StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), L"%SystemRoot%\\system32\\shell32.dll"); 1536 Entry->nIconIndex = -IDI_SHELL_FOLDER_OPTIONS; 1537 } 1538 1539 static BOOL 1540 InsertFileType(HWND hListView, LPCWSTR szName, INT iItem, LPCWSTR szFile) 1541 { 1542 PFOLDER_FILE_TYPE_ENTRY Entry; 1543 HKEY hKey; 1544 LVITEMW lvItem; 1545 DWORD dwSize; 1546 DWORD dwType; 1547 1548 if (szName[0] != L'.') 1549 { 1550 /* FIXME handle URL protocol handlers */ 1551 return FALSE; 1552 } 1553 1554 // get imagelists of listview 1555 HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); 1556 HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); 1557 1558 /* allocate file type entry */ 1559 Entry = (PFOLDER_FILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY)); 1560 if (!Entry) 1561 return FALSE; 1562 1563 /* open key */ 1564 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 1565 { 1566 HeapFree(GetProcessHeap(), 0, Entry); 1567 return FALSE; 1568 } 1569 1570 /* FIXME check for duplicates */ 1571 1572 /* query for the default key */ 1573 dwSize = sizeof(Entry->ClassKey); 1574 if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->ClassKey, &dwSize) != ERROR_SUCCESS) 1575 { 1576 /* no link available */ 1577 Entry->ClassKey[0] = 0; 1578 } 1579 1580 Entry->ClassName[0] = 0; 1581 if (Entry->ClassKey[0]) 1582 { 1583 HKEY hTemp; 1584 /* try open linked key */ 1585 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS) 1586 { 1587 DWORD dwSize = sizeof(Entry->ClassName); 1588 RegQueryValueExW(hTemp, NULL, NULL, NULL, LPBYTE(Entry->ClassName), &dwSize); 1589 1590 /* use linked key */ 1591 RegCloseKey(hKey); 1592 hKey = hTemp; 1593 } 1594 } 1595 1596 /* read friendly type name */ 1597 if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS) 1598 { 1599 /* read file description */ 1600 dwSize = sizeof(Entry->FileDescription); 1601 Entry->FileDescription[0] = 0; 1602 1603 /* read default key */ 1604 RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->FileDescription, &dwSize); 1605 } 1606 1607 /* Read the EditFlags value */ 1608 Entry->EditFlags = 0; 1609 if (!RegQueryValueExW(hKey, L"EditFlags", NULL, &dwType, NULL, &dwSize)) 1610 { 1611 if ((dwType == REG_DWORD || dwType == REG_BINARY) && dwSize == sizeof(DWORD)) 1612 RegQueryValueExW(hKey, L"EditFlags", NULL, NULL, (LPBYTE)&Entry->EditFlags, &dwSize); 1613 } 1614 1615 /* convert extension to upper case */ 1616 wcscpy(Entry->FileExtension, szName); 1617 _wcsupr(Entry->FileExtension); 1618 1619 /* get icon */ 1620 if (!GetFileTypeIconsByKey(hKey, Entry)) 1621 { 1622 // set default icon 1623 SetFileTypeEntryDefaultIcon(Entry); 1624 } 1625 1626 /* close key */ 1627 RegCloseKey(hKey); 1628 1629 // get program path and app name 1630 DWORD cch = _countof(Entry->ProgramPath); 1631 if (S_OK == AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, 1632 Entry->FileExtension, NULL, Entry->ProgramPath, &cch)) 1633 { 1634 QueryFileDescription(Entry->ProgramPath, Entry->AppName, _countof(Entry->AppName)); 1635 } 1636 else 1637 { 1638 Entry->ProgramPath[0] = Entry->AppName[0] = 0; 1639 } 1640 1641 // add icon to imagelist 1642 INT iLargeImage = -1, iSmallImage = -1; 1643 if (Entry->hIconLarge && Entry->hIconSmall) 1644 { 1645 iLargeImage = ImageList_AddIcon(himlLarge, Entry->hIconLarge); 1646 iSmallImage = ImageList_AddIcon(himlSmall, Entry->hIconSmall); 1647 ASSERT(iLargeImage == iSmallImage); 1648 } 1649 1650 /* Do not add excluded entries */ 1651 if (Entry->EditFlags & 0x00000001) //FTA_Exclude 1652 { 1653 DestroyIcon(Entry->hIconLarge); 1654 DestroyIcon(Entry->hIconSmall); 1655 HeapFree(GetProcessHeap(), 0, Entry); 1656 return FALSE; 1657 } 1658 1659 if (!Entry->FileDescription[0]) 1660 { 1661 /* construct default 'FileExtensionFile' by formatting the uppercase extension 1662 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */ 1663 1664 StringCchPrintf(Entry->FileDescription, _countof(Entry->FileDescription), szFile, &Entry->FileExtension[1]); 1665 } 1666 1667 ZeroMemory(&lvItem, sizeof(LVITEMW)); 1668 lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; 1669 lvItem.iSubItem = 0; 1670 lvItem.pszText = &Entry->FileExtension[1]; 1671 lvItem.iItem = iItem; 1672 lvItem.lParam = (LPARAM)Entry; 1673 lvItem.iImage = iSmallImage; 1674 SendMessageW(hListView, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); 1675 1676 ZeroMemory(&lvItem, sizeof(LVITEMW)); 1677 lvItem.mask = LVIF_TEXT; 1678 lvItem.pszText = Entry->FileDescription; 1679 lvItem.iItem = iItem; 1680 lvItem.iSubItem = 1; 1681 ListView_SetItem(hListView, &lvItem); 1682 1683 return TRUE; 1684 } 1685 1686 static 1687 int 1688 CALLBACK 1689 ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 1690 { 1691 PFOLDER_FILE_TYPE_ENTRY Entry1, Entry2; 1692 int x; 1693 1694 Entry1 = (PFOLDER_FILE_TYPE_ENTRY)lParam1; 1695 Entry2 = (PFOLDER_FILE_TYPE_ENTRY)lParam2; 1696 1697 x = wcsicmp(Entry1->FileExtension, Entry2->FileExtension); 1698 if (x != 0) 1699 return x; 1700 1701 return wcsicmp(Entry1->FileDescription, Entry2->FileDescription); 1702 } 1703 1704 static 1705 PFOLDER_FILE_TYPE_ENTRY 1706 InitializeFileTypesListCtrl(HWND hwndDlg) 1707 { 1708 HWND hDlgCtrl; 1709 DWORD dwIndex = 0; 1710 WCHAR szName[50]; 1711 WCHAR szFile[100]; 1712 DWORD dwName; 1713 LVITEMW lvItem; 1714 INT iItem = 0; 1715 HIMAGELIST himlLarge, himlSmall; 1716 1717 // create imagelists 1718 himlLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 1719 ILC_COLOR32 | ILC_MASK, 256, 20); 1720 himlSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 1721 ILC_COLOR32 | ILC_MASK, 256, 20); 1722 1723 // set imagelists to listview. 1724 hDlgCtrl = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 1725 ListView_SetImageList(hDlgCtrl, himlLarge, LVSIL_NORMAL); 1726 ListView_SetImageList(hDlgCtrl, himlSmall, LVSIL_SMALL); 1727 1728 InitializeFileTypesListCtrlColumns(hDlgCtrl); 1729 1730 szFile[0] = 0; 1731 if (!LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFile, _countof(szFile))) 1732 { 1733 /* default to english */ 1734 wcscpy(szFile, L"%s File"); 1735 } 1736 szFile[(_countof(szFile)) - 1] = 0; 1737 1738 dwName = _countof(szName); 1739 1740 while (RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 1741 { 1742 if (InsertFileType(hDlgCtrl, szName, iItem, szFile)) 1743 ++iItem; 1744 dwName = _countof(szName); 1745 } 1746 1747 /* Leave if the list is empty */ 1748 if (iItem == 0) 1749 return NULL; 1750 1751 /* sort list */ 1752 ListView_SortItems(hDlgCtrl, ListViewCompareProc, NULL); 1753 1754 /* select first item */ 1755 ZeroMemory(&lvItem, sizeof(LVITEMW)); 1756 lvItem.mask = LVIF_STATE; 1757 lvItem.stateMask = (UINT)-1; 1758 lvItem.state = LVIS_FOCUSED | LVIS_SELECTED; 1759 lvItem.iItem = 0; 1760 ListView_SetItem(hDlgCtrl, &lvItem); 1761 1762 lvItem.mask = LVIF_PARAM; 1763 ListView_GetItem(hDlgCtrl, &lvItem); 1764 1765 return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam; 1766 } 1767 1768 static inline 1769 PFOLDER_FILE_TYPE_ENTRY 1770 GetListViewEntry(HWND hListView, INT iItem = -1) 1771 { 1772 if (iItem == -1) 1773 { 1774 iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); 1775 if (iItem == -1) 1776 return NULL; 1777 } 1778 1779 LV_ITEMW lvItem = { LVIF_PARAM, iItem }; 1780 if (ListView_GetItem(hListView, &lvItem)) 1781 return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam; 1782 1783 return NULL; 1784 } 1785 1786 struct NEWEXT_DIALOG 1787 { 1788 HWND hwndLV; 1789 RECT rcDlg; 1790 BOOL bAdvanced; 1791 INT dy; 1792 WCHAR szExt[16]; 1793 WCHAR szFileType[64]; 1794 }; 1795 1796 static VOID 1797 NewExtDlg_OnAdvanced(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) 1798 { 1799 // If "Advanced" button was clicked, then we shrink or expand the dialog. 1800 WCHAR szText[64]; 1801 RECT rc, rc1, rc2; 1802 1803 GetWindowRect(hwndDlg, &rc); 1804 rc.bottom = rc.top + (pNewExt->rcDlg.bottom - pNewExt->rcDlg.top); 1805 1806 GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rc1); 1807 MapWindowPoints(NULL, hwndDlg, (POINT *)&rc1, 2); 1808 1809 GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rc2); 1810 MapWindowPoints(NULL, hwndDlg, (POINT *)&rc2, 2); 1811 1812 if (pNewExt->bAdvanced) 1813 { 1814 rc1.top += pNewExt->dy; 1815 rc1.bottom += pNewExt->dy; 1816 1817 rc2.top += pNewExt->dy; 1818 rc2.bottom += pNewExt->dy; 1819 1820 ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_SHOWNOACTIVATE); 1821 ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_SHOWNOACTIVATE); 1822 1823 LoadStringW(shell32_hInstance, IDS_NEWEXT_ADVANCED_LEFT, szText, _countof(szText)); 1824 SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, szText); 1825 1826 SetFocus(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX)); 1827 } 1828 else 1829 { 1830 rc1.top -= pNewExt->dy; 1831 rc1.bottom -= pNewExt->dy; 1832 1833 rc2.top -= pNewExt->dy; 1834 rc2.bottom -= pNewExt->dy; 1835 1836 ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_HIDE); 1837 ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_HIDE); 1838 1839 LoadStringW(shell32_hInstance, IDS_NEWEXT_ADVANCED_RIGHT, szText, _countof(szText)); 1840 SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, szText); 1841 1842 rc.bottom -= pNewExt->dy; 1843 1844 LoadStringW(shell32_hInstance, IDS_NEWEXT_NEW, szText, _countof(szText)); 1845 SetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, szText); 1846 } 1847 1848 HDWP hDWP = BeginDeferWindowPos(3); 1849 1850 if (hDWP) 1851 hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDOK), NULL, 1852 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top, 1853 SWP_NOACTIVATE | SWP_NOZORDER); 1854 if (hDWP) 1855 hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDCANCEL), NULL, 1856 rc2.left, rc2.top, rc2.right - rc2.left, rc2.bottom - rc2.top, 1857 SWP_NOACTIVATE | SWP_NOZORDER); 1858 if (hDWP) 1859 hDWP = DeferWindowPos(hDWP, hwndDlg, NULL, 1860 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 1861 SWP_NOACTIVATE | SWP_NOZORDER); 1862 1863 if (hDWP) 1864 EndDeferWindowPos(hDWP); 1865 } 1866 1867 static BOOL 1868 NewExtDlg_OnInitDialog(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) 1869 { 1870 WCHAR szText[64]; 1871 1872 pNewExt->bAdvanced = FALSE; 1873 1874 GetWindowRect(hwndDlg, &pNewExt->rcDlg); 1875 1876 RECT rc1, rc2; 1877 GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_EDIT), &rc1); 1878 GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), &rc2); 1879 pNewExt->dy = rc2.top - rc1.top; 1880 1881 LoadStringW(shell32_hInstance, IDS_NEWEXT_NEW, szText, _countof(szText)); 1882 SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_ADDSTRING, 0, (LPARAM)szText); 1883 SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_SETCURSEL, 0, 0); 1884 1885 SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_EDIT, EM_SETLIMITTEXT, _countof(pNewExt->szExt) - 1, 0); 1886 1887 NewExtDlg_OnAdvanced(hwndDlg, pNewExt); 1888 1889 return TRUE; 1890 } 1891 1892 static LPCWSTR s_pszSpace = L" \t\n\r\f\v"; 1893 1894 static BOOL 1895 NewExtDlg_OnOK(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) 1896 { 1897 LV_FINDINFO find; 1898 INT iItem; 1899 1900 GetDlgItemTextW(hwndDlg, IDC_NEWEXT_EDIT, pNewExt->szExt, _countof(pNewExt->szExt)); 1901 StrTrimW(pNewExt->szExt, s_pszSpace); 1902 CharUpperW(pNewExt->szExt); 1903 1904 GetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, pNewExt->szFileType, _countof(pNewExt->szFileType)); 1905 StrTrimW(pNewExt->szFileType, s_pszSpace); 1906 1907 if (pNewExt->szExt[0] == 0) 1908 { 1909 WCHAR szText[128], szTitle[128]; 1910 LoadStringW(shell32_hInstance, IDS_NEWEXT_SPECIFY_EXT, szText, _countof(szText)); 1911 szText[_countof(szText) - 1] = 0; 1912 LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szTitle, _countof(szTitle)); 1913 szTitle[_countof(szTitle) - 1] = 0; 1914 MessageBoxW(hwndDlg, szText, szTitle, MB_ICONERROR); 1915 return FALSE; 1916 } 1917 1918 ZeroMemory(&find, sizeof(find)); 1919 find.flags = LVFI_STRING; 1920 if (pNewExt->szExt[0] == L'.') 1921 { 1922 find.psz = &pNewExt->szExt[1]; 1923 } 1924 else 1925 { 1926 find.psz = pNewExt->szExt; 1927 } 1928 1929 iItem = ListView_FindItem(pNewExt->hwndLV, -1, &find); 1930 if (iItem >= 0) 1931 { 1932 // already exists 1933 WCHAR szText[256], szFormat[256], szTitle[64], szFileType[64]; 1934 1935 // get file type 1936 LV_ITEM item; 1937 ZeroMemory(&item, sizeof(item)); 1938 item.mask = LVIF_TEXT; 1939 item.pszText = szFileType; 1940 item.cchTextMax = _countof(szFileType); 1941 item.iItem = iItem; 1942 item.iSubItem = 1; 1943 ListView_GetItem(pNewExt->hwndLV, &item); 1944 1945 // get text 1946 LoadStringW(shell32_hInstance, IDS_NEWEXT_ALREADY_ASSOC, szFormat, _countof(szFormat)); 1947 szText[_countof(szFormat) - 1] = 0; 1948 StringCchPrintfW(szText, _countof(szText), szFormat, find.psz, szFileType, find.psz, szFileType); 1949 1950 // get title 1951 LoadStringW(shell32_hInstance, IDS_NEWEXT_EXT_IN_USE, szTitle, _countof(szTitle)); 1952 szTitle[_countof(szTitle) - 1] = 0; 1953 1954 if (MessageBoxW(hwndDlg, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDNO) 1955 { 1956 return FALSE; 1957 } 1958 1959 // Delete the extension 1960 CStringW strExt(L"."); 1961 strExt += find.psz; 1962 strExt.MakeLower(); 1963 DeleteExt(hwndDlg, strExt); 1964 1965 // Delete the item 1966 ListView_DeleteItem(pNewExt->hwndLV, iItem); 1967 } 1968 1969 EndDialog(hwndDlg, IDOK); 1970 return TRUE; 1971 } 1972 1973 // IDD_NEWEXTENSION dialog 1974 INT_PTR 1975 CALLBACK 1976 NewExtensionDlgProc( 1977 HWND hwndDlg, 1978 UINT uMsg, 1979 WPARAM wParam, 1980 LPARAM lParam) 1981 { 1982 static NEWEXT_DIALOG *s_pNewExt = NULL; 1983 1984 switch (uMsg) 1985 { 1986 case WM_INITDIALOG: 1987 s_pNewExt = (NEWEXT_DIALOG *)lParam; 1988 NewExtDlg_OnInitDialog(hwndDlg, s_pNewExt); 1989 return TRUE; 1990 1991 case WM_COMMAND: 1992 switch (LOWORD(wParam)) 1993 { 1994 case IDOK: 1995 NewExtDlg_OnOK(hwndDlg, s_pNewExt); 1996 break; 1997 1998 case IDCANCEL: 1999 EndDialog(hwndDlg, IDCANCEL); 2000 break; 2001 2002 case IDC_NEWEXT_ADVANCED: 2003 s_pNewExt->bAdvanced = !s_pNewExt->bAdvanced; 2004 NewExtDlg_OnAdvanced(hwndDlg, s_pNewExt); 2005 break; 2006 } 2007 break; 2008 } 2009 return 0; 2010 } 2011 2012 static BOOL 2013 FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR pszFileType) 2014 { 2015 DWORD dwValue = 1; 2016 HKEY hKey; 2017 WCHAR szKey[13]; // max. "ft4294967295" + "\0" 2018 LONG nResult; 2019 2020 // Search the next "ft%06u" key name 2021 do 2022 { 2023 StringCchPrintfW(szKey, _countof(szKey), TEXT("ft%06u"), dwValue); 2024 2025 nResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey); 2026 if (nResult != ERROR_SUCCESS) 2027 break; 2028 2029 RegCloseKey(hKey); 2030 ++dwValue; 2031 } while (dwValue != 0); 2032 2033 RegCloseKey(hKey); 2034 2035 if (dwValue == 0) 2036 return FALSE; 2037 2038 // Create new "ft%06u" key 2039 nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); 2040 if (ERROR_SUCCESS != nResult) 2041 return FALSE; 2042 2043 RegCloseKey(hKey); 2044 2045 // Create the ".ext" key 2046 WCHAR szExt[16]; 2047 if (*pszExt == L'.') 2048 ++pszExt; 2049 StringCchPrintfW(szExt, _countof(szExt), TEXT(".%s"), pszExt); 2050 CharLowerW(szExt); 2051 nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szExt, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); 2052 CharUpperW(szExt); 2053 if (ERROR_SUCCESS != nResult) 2054 return FALSE; 2055 2056 // Set the default value of ".ext" to "ft%06u" 2057 DWORD dwSize = (lstrlen(szKey) + 1) * sizeof(WCHAR); 2058 RegSetValueExW(hKey, NULL, 0, REG_SZ, (BYTE *)szKey, dwSize); 2059 2060 RegCloseKey(hKey); 2061 2062 // Make up the file type name 2063 WCHAR szFile[100], szFileFormat[100]; 2064 LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFileFormat, _countof(szFileFormat)); 2065 szFile[_countof(szFileFormat) - 1] = 0; 2066 StringCchPrintfW(szFile, _countof(szFile), szFileFormat, &szExt[1]); 2067 2068 // Insert an item to the listview 2069 HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 2070 INT iItem = ListView_GetItemCount(hListView); 2071 if (!InsertFileType(hListView, szExt, iItem, szFile)) 2072 return FALSE; 2073 2074 LV_ITEM item; 2075 ZeroMemory(&item, sizeof(item)); 2076 item.mask = LVIF_STATE | LVIF_TEXT; 2077 item.iItem = iItem; 2078 item.state = LVIS_SELECTED | LVIS_FOCUSED; 2079 item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 2080 item.pszText = &szExt[1]; 2081 ListView_SetItem(hListView, &item); 2082 2083 item.pszText = szFile; 2084 item.iSubItem = 1; 2085 ListView_SetItem(hListView, &item); 2086 2087 ListView_EnsureVisible(hListView, iItem, FALSE); 2088 2089 return TRUE; 2090 } 2091 2092 static BOOL 2093 FileTypesDlg_RemoveExt(HWND hwndDlg) 2094 { 2095 HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 2096 2097 INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); 2098 if (iItem == -1) 2099 return FALSE; 2100 2101 WCHAR szExt[20]; 2102 szExt[0] = L'.'; 2103 ListView_GetItemText(hListView, iItem, 0, &szExt[1], _countof(szExt) - 1); 2104 CharLowerW(szExt); 2105 2106 DeleteExt(hwndDlg, szExt); 2107 ListView_DeleteItem(hListView, iItem); 2108 return TRUE; 2109 } 2110 2111 static void 2112 FileTypesDlg_OnItemChanging(HWND hwndDlg, PFOLDER_FILE_TYPE_ENTRY pEntry) 2113 { 2114 WCHAR Buffer[255]; 2115 static HBITMAP s_hbmProgram = NULL; 2116 2117 // format buffer and set groupbox text 2118 CStringW strFormat(MAKEINTRESOURCEW(IDS_FILE_DETAILS)); 2119 StringCchPrintfW(Buffer, _countof(Buffer), strFormat, &pEntry->FileExtension[1]); 2120 SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DETAILS_GROUPBOX, Buffer); 2121 2122 // format buffer and set description 2123 strFormat.LoadString(IDS_FILE_DETAILSADV); 2124 StringCchPrintfW(Buffer, _countof(Buffer), strFormat, 2125 &pEntry->FileExtension[1], pEntry->FileDescription, 2126 pEntry->FileDescription); 2127 SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DESCRIPTION, Buffer); 2128 2129 // delete previous program image 2130 if (s_hbmProgram) 2131 { 2132 DeleteObject(s_hbmProgram); 2133 s_hbmProgram = NULL; 2134 } 2135 2136 // set program image 2137 HICON hIconSm = NULL; 2138 ExtractIconExW(pEntry->ProgramPath, 0, NULL, &hIconSm, 1); 2139 s_hbmProgram = BitmapFromIcon(hIconSm, 16, 16); 2140 DestroyIcon(hIconSm); 2141 SendDlgItemMessageW(hwndDlg, IDC_FILETYPES_ICON, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(s_hbmProgram)); 2142 2143 // set program name 2144 if (pEntry->AppName[0]) 2145 SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, pEntry->AppName); 2146 else 2147 SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, L"ReactOS"); 2148 2149 /* Enable the Delete button */ 2150 if (pEntry->EditFlags & 0x00000010) // FTA_NoRemove 2151 EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE); 2152 else 2153 EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), TRUE); 2154 } 2155 2156 struct EDITTYPE_DIALOG 2157 { 2158 HWND hwndLV; 2159 FOLDER_FILE_TYPE_ENTRY *pEntry; 2160 CSimpleMap<CStringW, CStringW> CommandLineMap; 2161 WCHAR szIconPath[MAX_PATH]; 2162 INT nIconIndex; 2163 WCHAR szDefaultVerb[64]; 2164 }; 2165 2166 static BOOL 2167 EditTypeDlg_ReadClass(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, LPCWSTR ClassKey) 2168 { 2169 // open class key 2170 HKEY hClassKey; 2171 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, KEY_READ, &hClassKey) != ERROR_SUCCESS) 2172 return FALSE; 2173 2174 // open "shell" key 2175 HKEY hShellKey; 2176 if (RegOpenKeyExW(hClassKey, L"shell", 0, KEY_READ, &hShellKey) != ERROR_SUCCESS) 2177 { 2178 RegCloseKey(hClassKey); 2179 return FALSE; 2180 } 2181 2182 WCHAR DefaultVerb[64]; 2183 DWORD dwSize = sizeof(DefaultVerb); 2184 if (RegQueryValueExW(hShellKey, NULL, NULL, NULL, LPBYTE(DefaultVerb), &dwSize) == ERROR_SUCCESS) 2185 { 2186 StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), DefaultVerb); 2187 } 2188 else 2189 { 2190 StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), L"open"); 2191 } 2192 2193 // enumerate shell verbs 2194 WCHAR szVerbName[64]; 2195 DWORD dwIndex = 0; 2196 while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) 2197 { 2198 // open verb key 2199 HKEY hVerbKey; 2200 LONG nResult = RegOpenKeyExW(hShellKey, szVerbName, 0, KEY_READ, &hVerbKey); 2201 if (nResult == ERROR_SUCCESS) 2202 { 2203 // open command key 2204 HKEY hCommandKey; 2205 nResult = RegOpenKeyExW(hVerbKey, L"command", 0, KEY_READ, &hCommandKey); 2206 if (nResult == ERROR_SUCCESS) 2207 { 2208 // get command line 2209 WCHAR szValue[MAX_PATH + 32]; 2210 dwSize = sizeof(szValue); 2211 nResult = RegQueryValueExW(hCommandKey, NULL, NULL, NULL, LPBYTE(szValue), &dwSize); 2212 if (nResult == ERROR_SUCCESS) 2213 { 2214 pEditType->CommandLineMap.SetAt(szVerbName, szValue); 2215 } 2216 2217 RegCloseKey(hCommandKey); 2218 } 2219 2220 RegCloseKey(hVerbKey); 2221 } 2222 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_ADDSTRING, 0, LPARAM(szVerbName)); 2223 ++dwIndex; 2224 } 2225 2226 RegCloseKey(hShellKey); 2227 RegCloseKey(hClassKey); 2228 2229 return TRUE; 2230 } 2231 2232 static BOOL 2233 EditTypeDlg_WriteClass(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, 2234 LPCWSTR ClassKey, LPCWSTR ClassName, INT cchName) 2235 { 2236 FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; 2237 2238 if (ClassKey[0] == 0) 2239 return FALSE; 2240 2241 // create or open class key 2242 HKEY hClassKey; 2243 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, NULL, 0, KEY_WRITE, NULL, &hClassKey, NULL) != ERROR_SUCCESS) 2244 return FALSE; 2245 2246 // create "DefaultIcon" key 2247 if (pEntry->IconPath[0]) 2248 { 2249 HKEY hDefaultIconKey; 2250 if (RegCreateKeyExW(hClassKey, L"DefaultIcon", 0, NULL, 0, KEY_WRITE, NULL, &hDefaultIconKey, NULL) == ERROR_SUCCESS) 2251 { 2252 WCHAR szText[MAX_PATH]; 2253 StringCchPrintfW(szText, _countof(szText), L"%s,%d", pEntry->IconPath, pEntry->nIconIndex); 2254 2255 // set icon location 2256 DWORD dwSize = (lstrlenW(szText) + 1) * sizeof(WCHAR); 2257 RegSetValueExW(hDefaultIconKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(szText), dwSize); 2258 2259 RegCloseKey(hDefaultIconKey); 2260 } 2261 } 2262 2263 // create "shell" key 2264 HKEY hShellKey; 2265 if (RegCreateKeyExW(hClassKey, L"shell", 0, NULL, 0, KEY_WRITE, NULL, &hShellKey, NULL) != ERROR_SUCCESS) 2266 { 2267 RegCloseKey(hClassKey); 2268 return FALSE; 2269 } 2270 2271 // delete shell commands 2272 WCHAR szVerbName[64]; 2273 DWORD dwIndex = 0; 2274 while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) 2275 { 2276 if (pEditType->CommandLineMap.FindKey(szVerbName) == -1) 2277 { 2278 // doesn't exist in CommandLineMap, then delete it 2279 if (SHDeleteKeyW(hShellKey, szVerbName) == ERROR_SUCCESS) 2280 { 2281 --dwIndex; 2282 } 2283 } 2284 ++dwIndex; 2285 } 2286 2287 // set default action 2288 RegSetValueExW(hShellKey, NULL, 0, REG_SZ, LPBYTE(pEditType->szDefaultVerb), sizeof(pEditType->szDefaultVerb)); 2289 2290 // write shell commands 2291 const INT nCount = pEditType->CommandLineMap.GetSize(); 2292 for (INT i = 0; i < nCount; ++i) 2293 { 2294 CStringW& key = pEditType->CommandLineMap.GetKeyAt(i); 2295 CStringW& value = pEditType->CommandLineMap.GetValueAt(i); 2296 2297 // create verb key 2298 HKEY hVerbKey; 2299 if (RegCreateKeyExW(hShellKey, key, 0, NULL, 0, KEY_WRITE, NULL, &hVerbKey, NULL) == ERROR_SUCCESS) 2300 { 2301 // create command key 2302 HKEY hCommandKey; 2303 if (RegCreateKeyExW(hVerbKey, L"command", 0, NULL, 0, KEY_WRITE, NULL, &hCommandKey, NULL) == ERROR_SUCCESS) 2304 { 2305 // write the default value 2306 DWORD dwSize = (value.GetLength() + 1) * sizeof(WCHAR); 2307 RegSetValueExW(hCommandKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(LPCWSTR(value)), dwSize); 2308 2309 RegCloseKey(hCommandKey); 2310 } 2311 2312 RegCloseKey(hVerbKey); 2313 } 2314 } 2315 2316 // set class name to class key 2317 RegSetValueExW(hClassKey, NULL, 0, REG_SZ, LPBYTE(ClassName), cchName); 2318 2319 RegCloseKey(hShellKey); 2320 RegCloseKey(hClassKey); 2321 2322 return TRUE; 2323 } 2324 2325 static BOOL 2326 EditTypeDlg_OnInitDialog(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) 2327 { 2328 FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; 2329 StringCchCopyW(pEditType->szIconPath, _countof(pEditType->szIconPath), pEntry->IconPath); 2330 pEditType->nIconIndex = pEntry->nIconIndex; 2331 StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), L"open"); 2332 2333 // set info 2334 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); 2335 SetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName); 2336 EditTypeDlg_ReadClass(hwndDlg, pEditType, pEntry->ClassKey); 2337 InvalidateRect(GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX), NULL, TRUE); 2338 2339 // is listbox empty? 2340 if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCOUNT, 0, 0) == 0) 2341 { 2342 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_EDIT_BUTTON), FALSE); 2343 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_REMOVE), FALSE); 2344 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); 2345 } 2346 else 2347 { 2348 // select first item 2349 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_SETCURSEL, 0, 0); 2350 } 2351 2352 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SAME_WINDOW), FALSE); 2353 2354 return TRUE; 2355 } 2356 2357 static BOOL 2358 EditTypeDlg_OnRemove(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) 2359 { 2360 // get current selection 2361 INT iItem = SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCURSEL, 0, 0); 2362 if (iItem == LB_ERR) 2363 return FALSE; 2364 2365 // ask user for removal 2366 CStringW strText(MAKEINTRESOURCEW(IDS_REMOVE_ACTION)); 2367 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2368 if (MessageBoxW(hwndDlg, strText, strTitle, MB_ICONINFORMATION | MB_YESNO) == IDNO) 2369 return FALSE; 2370 2371 // get text 2372 WCHAR szText[64]; 2373 szText[0] = 0; 2374 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, iItem, (LPARAM)szText); 2375 StrTrimW(szText, s_pszSpace); 2376 2377 // remove it 2378 pEditType->CommandLineMap.Remove(szText); 2379 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_DELETESTRING, iItem, 0); 2380 return TRUE; 2381 } 2382 2383 static BOOL 2384 EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, LPCWSTR IconPath, INT IconIndex) 2385 { 2386 FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; 2387 2388 BOOL bIconSet = FALSE; 2389 if (IconPath && IconPath[0]) 2390 { 2391 DestroyIcon(pEntry->hIconLarge); 2392 DestroyIcon(pEntry->hIconSmall); 2393 pEntry->hIconLarge = DoExtractIcon(pEntry, IconPath, IconIndex, FALSE); 2394 pEntry->hIconSmall = DoExtractIcon(pEntry, IconPath, IconIndex, TRUE); 2395 2396 bIconSet = (pEntry->hIconLarge && pEntry->hIconSmall); 2397 } 2398 if (bIconSet) 2399 { 2400 StringCchCopyW(pEntry->IconPath, _countof(pEntry->IconPath), IconPath); 2401 pEntry->nIconIndex = IconIndex; 2402 } 2403 else 2404 { 2405 SetFileTypeEntryDefaultIcon(pEntry); 2406 } 2407 2408 HWND hListView = pEditType->hwndLV; 2409 HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); 2410 HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); 2411 2412 INT iLargeImage = ImageList_AddIcon(himlLarge, pEntry->hIconLarge); 2413 INT iSmallImage = ImageList_AddIcon(himlSmall, pEntry->hIconSmall); 2414 ASSERT(iLargeImage == iSmallImage); 2415 2416 INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); 2417 if (iItem != -1) 2418 { 2419 LV_ITEMW Item = { LVIF_IMAGE, iItem }; 2420 Item.iImage = iSmallImage; 2421 ListView_SetItem(hListView, &Item); 2422 } 2423 return TRUE; 2424 } 2425 2426 static void 2427 EditTypeDlg_OnOK(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) 2428 { 2429 FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; 2430 2431 // get class name 2432 GetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName, _countof(pEntry->ClassName)); 2433 StrTrimW(pEntry->ClassName, s_pszSpace); 2434 2435 // update entry icon 2436 EditTypeDlg_UpdateEntryIcon(hwndDlg, pEditType, pEditType->szIconPath, pEditType->nIconIndex); 2437 2438 // write registry 2439 EditTypeDlg_WriteClass(hwndDlg, pEditType, pEntry->ClassKey, pEntry->ClassName, _countof(pEntry->ClassName)); 2440 2441 // update the icon cache 2442 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL); 2443 2444 EndDialog(hwndDlg, IDOK); 2445 } 2446 2447 struct ACTION_DIALOG 2448 { 2449 HWND hwndLB; 2450 WCHAR ClassName[64]; 2451 WCHAR szAction[64]; 2452 WCHAR szApp[MAX_PATH]; 2453 BOOL bUseDDE; 2454 }; 2455 2456 static void 2457 NewAct_OnOK(HWND hwndDlg, ACTION_DIALOG *pNewAct) 2458 { 2459 GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pNewAct->szAction, _countof(pNewAct->szAction)); 2460 GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pNewAct->szApp, _countof(pNewAct->szApp)); 2461 StrTrimW(pNewAct->szAction, s_pszSpace); 2462 StrTrimW(pNewAct->szApp, s_pszSpace); 2463 if (pNewAct->szAction[0] == 0) 2464 { 2465 // action is empty, error 2466 HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); 2467 SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); 2468 SetFocus(hwndCtrl); 2469 CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); 2470 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2471 MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); 2472 return; 2473 } 2474 if (pNewAct->szApp[0] == 0 || GetFileAttributesW(pNewAct->szApp) == 0xFFFFFFFF) 2475 { 2476 // app is invalid 2477 HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); 2478 SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); 2479 SetFocus(hwndCtrl); 2480 CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); 2481 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2482 MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); 2483 return; 2484 } 2485 EndDialog(hwndDlg, IDOK); 2486 } 2487 2488 static void 2489 Action_OnBrowse(HWND hwndDlg, ACTION_DIALOG *pNewAct, BOOL bEdit = FALSE) 2490 { 2491 WCHAR szFile[MAX_PATH]; 2492 szFile[0] = 0; 2493 2494 WCHAR szFilter[MAX_PATH]; 2495 LoadStringW(shell32_hInstance, IDS_EXE_FILTER, szFilter, _countof(szFilter)); 2496 2497 CStringW strTitle(MAKEINTRESOURCEW(IDS_OPEN_WITH)); 2498 2499 OPENFILENAMEW ofn; 2500 ZeroMemory(&ofn, sizeof(ofn)); 2501 ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400W; 2502 ofn.hwndOwner = hwndDlg; 2503 ofn.lpstrFilter = szFilter; 2504 ofn.lpstrFile = szFile; 2505 ofn.nMaxFile = _countof(szFile); 2506 ofn.lpstrTitle = strTitle; 2507 ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; 2508 ofn.lpstrDefExt = L"exe"; 2509 if (GetOpenFileNameW(&ofn)) 2510 { 2511 if (bEdit) 2512 { 2513 CStringW str = szFile; 2514 str += L" \"%1\""; 2515 SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, str); 2516 } 2517 else 2518 { 2519 SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, szFile); 2520 } 2521 } 2522 } 2523 2524 INT_PTR CALLBACK 2525 NewActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 2526 { 2527 static ACTION_DIALOG *s_pNewAct = NULL; 2528 2529 switch (uMsg) 2530 { 2531 case WM_INITDIALOG: 2532 s_pNewAct = (ACTION_DIALOG *)lParam; 2533 s_pNewAct->bUseDDE = FALSE; 2534 EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); 2535 return TRUE; 2536 2537 case WM_COMMAND: 2538 switch (LOWORD(wParam)) 2539 { 2540 case IDOK: 2541 NewAct_OnOK(hwndDlg, s_pNewAct); 2542 break; 2543 2544 case IDCANCEL: 2545 EndDialog(hwndDlg, IDCANCEL); 2546 break; 2547 2548 case IDC_ACTION_BROWSE: 2549 Action_OnBrowse(hwndDlg, s_pNewAct, FALSE); 2550 break; 2551 } 2552 break; 2553 } 2554 return 0; 2555 } 2556 2557 static void 2558 EditAct_OnOK(HWND hwndDlg, ACTION_DIALOG *pEditAct) 2559 { 2560 GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pEditAct->szAction, _countof(pEditAct->szAction)); 2561 GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pEditAct->szApp, _countof(pEditAct->szApp)); 2562 StrTrimW(pEditAct->szAction, s_pszSpace); 2563 StrTrimW(pEditAct->szApp, s_pszSpace); 2564 if (pEditAct->szAction[0] == 0) 2565 { 2566 HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); 2567 SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); 2568 SetFocus(hwndCtrl); 2569 CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); 2570 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2571 MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); 2572 } 2573 if (pEditAct->szApp[0] == 0) 2574 { 2575 HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); 2576 SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); 2577 SetFocus(hwndCtrl); 2578 CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); 2579 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2580 MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); 2581 } 2582 EndDialog(hwndDlg, IDOK); 2583 } 2584 2585 INT_PTR CALLBACK 2586 EditActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 2587 { 2588 static ACTION_DIALOG *s_pEditAct = NULL; 2589 2590 switch (uMsg) 2591 { 2592 case WM_INITDIALOG: 2593 s_pEditAct = (ACTION_DIALOG *)lParam; 2594 s_pEditAct->bUseDDE = FALSE; 2595 SetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, s_pEditAct->szAction); 2596 SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, s_pEditAct->szApp); 2597 EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); 2598 EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_ACTION), FALSE); 2599 { 2600 // set title 2601 CStringW str(MAKEINTRESOURCEW(IDS_EDITING_ACTION)); 2602 str += s_pEditAct->ClassName; 2603 SetWindowTextW(hwndDlg, str); 2604 } 2605 return TRUE; 2606 2607 case WM_COMMAND: 2608 switch (LOWORD(wParam)) 2609 { 2610 case IDOK: 2611 EditAct_OnOK(hwndDlg, s_pEditAct); 2612 break; 2613 2614 case IDCANCEL: 2615 EndDialog(hwndDlg, IDCANCEL); 2616 break; 2617 2618 case IDC_ACTION_BROWSE: 2619 Action_OnBrowse(hwndDlg, s_pEditAct, TRUE); 2620 break; 2621 } 2622 break; 2623 } 2624 return 0; 2625 } 2626 2627 static void 2628 EditTypeDlg_OnChangeIcon(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) 2629 { 2630 WCHAR szPath[MAX_PATH]; 2631 INT IconIndex; 2632 2633 ExpandEnvironmentStringsW(pEditType->szIconPath, szPath, _countof(szPath)); 2634 IconIndex = pEditType->nIconIndex; 2635 if (PickIconDlg(hwndDlg, szPath, _countof(szPath), &IconIndex)) 2636 { 2637 // replace Windows directory with "%SystemRoot%" (for portability) 2638 WCHAR szWinDir[MAX_PATH]; 2639 GetWindowsDirectoryW(szWinDir, _countof(szWinDir)); 2640 if (wcsstr(szPath, szWinDir) == 0) 2641 { 2642 CStringW str(L"%SystemRoot%"); 2643 str += &szPath[wcslen(szWinDir)]; 2644 StringCchCopyW(szPath, _countof(szPath), LPCWSTR(str)); 2645 } 2646 2647 // update FOLDER_FILE_TYPE_ENTRY 2648 FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; 2649 DestroyIcon(pEntry->hIconLarge); 2650 DestroyIcon(pEntry->hIconSmall); 2651 pEntry->hIconLarge = DoExtractIcon(pEntry, szPath, IconIndex, FALSE); 2652 pEntry->hIconSmall = DoExtractIcon(pEntry, szPath, IconIndex, TRUE); 2653 2654 // update EDITTYPE_DIALOG 2655 StringCchCopyW(pEditType->szIconPath, _countof(pEditType->szIconPath), szPath); 2656 pEditType->nIconIndex = IconIndex; 2657 2658 // set icon to dialog 2659 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); 2660 } 2661 } 2662 2663 static BOOL 2664 EditTypeDlg_OnDrawItem(HWND hwndDlg, LPDRAWITEMSTRUCT pDraw, EDITTYPE_DIALOG *pEditType) 2665 { 2666 WCHAR szText[64]; 2667 HFONT hFont, hFont2; 2668 2669 if (!pDraw) 2670 return FALSE; 2671 2672 // fill rect and set colors 2673 if (pDraw->itemState & ODS_SELECTED) 2674 { 2675 FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_HIGHLIGHT + 1)); 2676 SetTextColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 2677 SetBkColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHT)); 2678 } 2679 else 2680 { 2681 FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_WINDOW + 1)); 2682 SetTextColor(pDraw->hDC, GetSysColor(COLOR_WINDOWTEXT)); 2683 SetBkColor(pDraw->hDC, GetSysColor(COLOR_WINDOW)); 2684 } 2685 2686 // get listbox text 2687 SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, pDraw->itemID, (LPARAM)szText); 2688 2689 // is it default? 2690 hFont = (HFONT)SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, WM_GETFONT, 0, 0); 2691 if (lstrcmpiW(pEditType->szDefaultVerb, szText) == 0) 2692 { 2693 // default. set bold 2694 LOGFONTW lf; 2695 GetObject(hFont, sizeof(lf), &lf); 2696 lf.lfWeight = FW_BOLD; 2697 hFont2 = CreateFontIndirectW(&lf); 2698 if (hFont2) 2699 { 2700 HGDIOBJ hFontOld = SelectObject(pDraw->hDC, hFont2); 2701 InflateRect(&pDraw->rcItem, -2, -2); 2702 DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); 2703 InflateRect(&pDraw->rcItem, 2, 2); 2704 SelectObject(pDraw->hDC, hFontOld); 2705 DeleteObject(hFont2); 2706 } 2707 } 2708 else 2709 { 2710 // non-default 2711 InflateRect(&pDraw->rcItem, -2, -2); 2712 DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); 2713 InflateRect(&pDraw->rcItem, 2, 2); 2714 } 2715 2716 // draw focus rect 2717 if (pDraw->itemState & ODS_FOCUS) 2718 { 2719 DrawFocusRect(pDraw->hDC, &pDraw->rcItem); 2720 } 2721 return TRUE; 2722 } 2723 2724 static BOOL 2725 EditTypeDlg_OnMeasureItem(HWND hwndDlg, LPMEASUREITEMSTRUCT pMeasure, EDITTYPE_DIALOG *pEditType) 2726 { 2727 if (!pMeasure) 2728 return FALSE; 2729 2730 HWND hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); 2731 2732 RECT rc; 2733 GetClientRect(hwndLB, &rc); 2734 2735 HDC hDC = GetDC(hwndLB); 2736 if (hDC) 2737 { 2738 TEXTMETRICW tm; 2739 GetTextMetricsW(hDC, &tm); 2740 pMeasure->itemWidth = rc.right - rc.left; 2741 pMeasure->itemHeight = tm.tmHeight + 4; 2742 ReleaseDC(hwndLB, hDC); 2743 return TRUE; 2744 } 2745 return FALSE; 2746 } 2747 2748 static void 2749 EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, EDITTYPE_DIALOG *pEditType) 2750 { 2751 INT iItem, iIndex; 2752 ACTION_DIALOG action; 2753 switch (id) 2754 { 2755 case IDOK: 2756 EditTypeDlg_OnOK(hwndDlg, pEditType); 2757 break; 2758 2759 case IDCANCEL: 2760 EndDialog(hwndDlg, IDCANCEL); 2761 break; 2762 2763 case IDC_EDITTYPE_CHANGE_ICON: 2764 EditTypeDlg_OnChangeIcon(hwndDlg, pEditType); 2765 break; 2766 2767 case IDC_EDITTYPE_NEW: 2768 action.bUseDDE = FALSE; 2769 action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); 2770 StringCchPrintfW(action.ClassName, _countof(action.ClassName), pEditType->pEntry->ClassName); 2771 // open 'New Action' dialog 2772 if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, 2773 NewActionDlgProc, LPARAM(&action))) 2774 { 2775 if (SendMessageW(action.hwndLB, LB_FINDSTRING, -1, (LPARAM)action.szAction) != LB_ERR) 2776 { 2777 // already exists, error 2778 HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); 2779 SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); 2780 SetFocus(hwndCtrl); 2781 2782 CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2783 strText.Format(IDS_ACTION_EXISTS, action.szAction); 2784 MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); 2785 } 2786 else 2787 { 2788 // add it 2789 CStringW strCommandLine = action.szApp; 2790 strCommandLine += L" \"%1\""; 2791 pEditType->CommandLineMap.SetAt(action.szAction, strCommandLine); 2792 SendMessageW(action.hwndLB, LB_ADDSTRING, 0, LPARAM(action.szAction)); 2793 if (SendMessageW(action.hwndLB, LB_GETCOUNT, 0, 0) == 1) 2794 { 2795 // set default 2796 StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), action.szAction); 2797 InvalidateRect(action.hwndLB, NULL, TRUE); 2798 } 2799 } 2800 } 2801 break; 2802 2803 case IDC_EDITTYPE_LISTBOX: 2804 if (code == LBN_SELCHANGE) 2805 { 2806 action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); 2807 INT iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); 2808 SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); 2809 if (lstrcmpiW(action.szAction, pEditType->szDefaultVerb) == 0) 2810 { 2811 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); 2812 } 2813 else 2814 { 2815 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), TRUE); 2816 } 2817 break; 2818 } 2819 else if (code != LBN_DBLCLK) 2820 { 2821 break; 2822 } 2823 // FALL THROUGH 2824 2825 case IDC_EDITTYPE_EDIT_BUTTON: 2826 action.bUseDDE = FALSE; 2827 action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); 2828 StringCchPrintfW(action.ClassName, _countof(action.ClassName), pEditType->pEntry->ClassName); 2829 iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); 2830 if (iItem == LB_ERR) 2831 break; 2832 2833 // get action 2834 SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); 2835 2836 // get app 2837 { 2838 iIndex = pEditType->CommandLineMap.FindKey(action.szAction); 2839 CStringW str = pEditType->CommandLineMap.GetValueAt(iIndex); 2840 StringCchCopyW(action.szApp, _countof(action.szApp), LPCWSTR(str)); 2841 } 2842 2843 // open dialog 2844 if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, 2845 EditActionDlgProc, LPARAM(&action))) 2846 { 2847 SendMessageW(action.hwndLB, LB_DELETESTRING, iItem, 0); 2848 SendMessageW(action.hwndLB, LB_INSERTSTRING, iItem, LPARAM(action.szAction)); 2849 pEditType->CommandLineMap.SetAt(action.szAction, action.szApp); 2850 } 2851 break; 2852 2853 case IDC_EDITTYPE_REMOVE: 2854 EditTypeDlg_OnRemove(hwndDlg, pEditType); 2855 break; 2856 2857 case IDC_EDITTYPE_SET_DEFAULT: 2858 action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); 2859 iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); 2860 if (iItem == LB_ERR) 2861 break; 2862 2863 SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); 2864 2865 // set default 2866 StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), action.szAction); 2867 EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); 2868 InvalidateRect(action.hwndLB, NULL, TRUE); 2869 break; 2870 } 2871 } 2872 2873 INT_PTR CALLBACK 2874 EditTypeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 2875 { 2876 static EDITTYPE_DIALOG *s_pEditType = NULL; 2877 LPDRAWITEMSTRUCT pDraw; 2878 LPMEASUREITEMSTRUCT pMeasure; 2879 2880 switch (uMsg) 2881 { 2882 case WM_INITDIALOG: 2883 s_pEditType = (EDITTYPE_DIALOG *)lParam; 2884 return EditTypeDlg_OnInitDialog(hwndDlg, s_pEditType); 2885 2886 case WM_DRAWITEM: 2887 pDraw = LPDRAWITEMSTRUCT(lParam); 2888 return EditTypeDlg_OnDrawItem(hwndDlg, pDraw, s_pEditType); 2889 2890 case WM_MEASUREITEM: 2891 pMeasure = LPMEASUREITEMSTRUCT(lParam); 2892 return EditTypeDlg_OnMeasureItem(hwndDlg, pMeasure, s_pEditType); 2893 2894 case WM_COMMAND: 2895 EditTypeDlg_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), s_pEditType); 2896 break; 2897 } 2898 2899 return 0; 2900 } 2901 2902 static void 2903 EditTypeDlg_OnDelete(HWND hwndDlg) 2904 { 2905 CStringW strRemoveExt(MAKEINTRESOURCEW(IDS_REMOVE_EXT)); 2906 CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); 2907 if (MessageBoxW(hwndDlg, strRemoveExt, strTitle, MB_ICONQUESTION | MB_YESNO) == IDYES) 2908 { 2909 FileTypesDlg_RemoveExt(hwndDlg); 2910 } 2911 } 2912 2913 // IDD_FOLDER_OPTIONS_FILETYPES dialog 2914 INT_PTR 2915 CALLBACK 2916 FolderOptionsFileTypesDlg( 2917 HWND hwndDlg, 2918 UINT uMsg, 2919 WPARAM wParam, 2920 LPARAM lParam) 2921 { 2922 LPNMLISTVIEW lppl; 2923 PFOLDER_FILE_TYPE_ENTRY pItem; 2924 OPENASINFO Info; 2925 NEWEXT_DIALOG newext; 2926 EDITTYPE_DIALOG edittype; 2927 2928 switch(uMsg) 2929 { 2930 case WM_INITDIALOG: 2931 pItem = InitializeFileTypesListCtrl(hwndDlg); 2932 2933 /* Disable the Delete button if the listview is empty or 2934 the selected item should not be deleted by the user */ 2935 if (pItem == NULL || (pItem->EditFlags & 0x00000010)) // FTA_NoRemove 2936 EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE); 2937 return TRUE; 2938 2939 case WM_COMMAND: 2940 switch(LOWORD(wParam)) 2941 { 2942 case IDC_FILETYPES_NEW: 2943 newext.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 2944 if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_NEWEXTENSION), 2945 hwndDlg, NewExtensionDlgProc, (LPARAM)&newext)) 2946 { 2947 FileTypesDlg_AddExt(hwndDlg, newext.szExt, newext.szFileType); 2948 } 2949 break; 2950 2951 case IDC_FILETYPES_DELETE: 2952 EditTypeDlg_OnDelete(hwndDlg); 2953 break; 2954 2955 case IDC_FILETYPES_CHANGE: 2956 pItem = GetListViewEntry(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); 2957 if (pItem) 2958 { 2959 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT; 2960 Info.pcszClass = pItem->FileExtension; 2961 SHOpenWithDialog(hwndDlg, &Info); 2962 } 2963 break; 2964 2965 case IDC_FILETYPES_ADVANCED: 2966 edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 2967 edittype.pEntry = GetListViewEntry(edittype.hwndLV); 2968 DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), 2969 hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); 2970 break; 2971 } 2972 break; 2973 2974 case WM_NOTIFY: 2975 lppl = (LPNMLISTVIEW) lParam; 2976 switch (lppl->hdr.code) 2977 { 2978 case LVN_KEYDOWN: 2979 { 2980 LV_KEYDOWN *pKeyDown = (LV_KEYDOWN *)lParam; 2981 if (pKeyDown->wVKey == VK_DELETE) 2982 { 2983 EditTypeDlg_OnDelete(hwndDlg); 2984 } 2985 break; 2986 } 2987 2988 case NM_DBLCLK: 2989 edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); 2990 edittype.pEntry = GetListViewEntry(edittype.hwndLV); 2991 DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), 2992 hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); 2993 break; 2994 2995 case LVN_DELETEALLITEMS: 2996 return FALSE; // send LVN_DELETEITEM 2997 2998 case LVN_DELETEITEM: 2999 pItem = GetListViewEntry(lppl->hdr.hwndFrom, lppl->iItem); 3000 if (pItem) 3001 { 3002 DestroyIcon(pItem->hIconLarge); 3003 DestroyIcon(pItem->hIconSmall); 3004 HeapFree(GetProcessHeap(), 0, pItem); 3005 } 3006 return FALSE; 3007 3008 case LVN_ITEMCHANGING: 3009 pItem = GetListViewEntry(lppl->hdr.hwndFrom, lppl->iItem); 3010 if (!pItem) 3011 { 3012 return TRUE; 3013 } 3014 3015 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED)) 3016 { 3017 FileTypesDlg_OnItemChanging(hwndDlg, pItem); 3018 } 3019 break; 3020 3021 case PSN_SETACTIVE: 3022 /* On page activation, set the focus to the listview */ 3023 SetFocus(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); 3024 break; 3025 } 3026 break; 3027 } 3028 3029 return FALSE; 3030 } 3031 3032 static 3033 VOID 3034 ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst) 3035 { 3036 PROPSHEETHEADERW pinfo; 3037 HPROPSHEETPAGE hppages[3]; 3038 HPROPSHEETPAGE hpage; 3039 UINT num_pages = 0; 3040 WCHAR szOptions[100]; 3041 3042 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL); 3043 if (hpage) 3044 hppages[num_pages++] = hpage; 3045 3046 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL); 3047 if (hpage) 3048 hppages[num_pages++] = hpage; 3049 3050 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL); 3051 if (hpage) 3052 hppages[num_pages++] = hpage; 3053 3054 szOptions[0] = L'\0'; 3055 LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR)); 3056 szOptions[(sizeof(szOptions)/sizeof(WCHAR))-1] = L'\0'; 3057 3058 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); 3059 pinfo.dwSize = sizeof(PROPSHEETHEADERW); 3060 pinfo.dwFlags = PSH_NOCONTEXTHELP; 3061 pinfo.nPages = num_pages; 3062 pinfo.phpage = hppages; 3063 pinfo.pszCaption = szOptions; 3064 3065 PropertySheetW(&pinfo); 3066 } 3067 3068 static 3069 VOID 3070 Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) 3071 { 3072 switch(fOptions) 3073 { 3074 case 0: 3075 ShowFolderOptionsDialog(hWnd, hInst); 3076 break; 3077 3078 case 1: 3079 // show taskbar options dialog 3080 FIXME("notify explorer to show taskbar options dialog"); 3081 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0); 3082 break; 3083 3084 default: 3085 FIXME("unrecognized options id %d\n", fOptions); 3086 } 3087 } 3088 3089 /************************************************************************* 3090 * Options_RunDLL (SHELL32.@) 3091 */ 3092 EXTERN_C VOID WINAPI Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 3093 { 3094 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 3095 } 3096 3097 /************************************************************************* 3098 * Options_RunDLLA (SHELL32.@) 3099 */ 3100 EXTERN_C VOID WINAPI Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 3101 { 3102 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 3103 } 3104 3105 /************************************************************************* 3106 * Options_RunDLLW (SHELL32.@) 3107 */ 3108 EXTERN_C VOID WINAPI Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) 3109 { 3110 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow); 3111 } 3112