2 * Open With Context Menu extension
4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
5 * Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
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.
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.
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
24 WINE_DEFAULT_DEBUG_CHANNEL (fprop
);
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
32 /// ShellFolder Attributes: 0x0
36 WCHAR FileExtension
[30];
37 WCHAR FileDescription
[100];
38 WCHAR ClassKey
[MAX_PATH
];
44 WCHAR ProgramPath
[MAX_PATH
];
45 WCHAR IconPath
[MAX_PATH
];
47 } FOLDER_FILE_TYPE_ENTRY
, *PFOLDER_FILE_TYPE_ENTRY
;
49 // uniquely-defined icon entry for Advanced Settings
50 typedef struct ADVANCED_ICON
52 WCHAR szPath
[MAX_PATH
];
56 // predefined icon IDs (See CreateTreeImageList function below)
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
66 #define PREDEFINED_ICON_COUNT 8
68 // definition of icon stock
69 static ADVANCED_ICON
* s_AdvancedIcons
= NULL
;
70 static INT s_AdvancedIconCount
= 0;
71 static HIMAGELIST s_hImageList
= NULL
;
74 Advanced_FindIcon(LPCWSTR pszPath
, UINT nIconIndex
)
76 for (INT i
= PREDEFINED_ICON_COUNT
; i
< s_AdvancedIconCount
; ++i
)
78 ADVANCED_ICON
*pIcon
= &s_AdvancedIcons
[i
];
79 if (pIcon
->nIconIndex
== nIconIndex
&&
80 lstrcmpiW(pIcon
->szPath
, pszPath
) == 0)
85 return -1; // not found
89 Advanced_AddIcon(LPCWSTR pszPath
, UINT nIconIndex
)
91 ADVANCED_ICON
*pAllocated
;
93 // return the ID if already existed
94 INT nIconID
= Advanced_FindIcon(pszPath
, nIconIndex
);
96 return nIconID
; // already exists
98 // extract a small icon
99 HICON hIconSmall
= NULL
;
100 ExtractIconExW(pszPath
, nIconIndex
, NULL
, &hIconSmall
, 1);
101 if (hIconSmall
== NULL
)
102 return -1; // failure
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
110 s_AdvancedIcons
= pAllocated
;
112 // save icon information
113 ADVANCED_ICON
*pIcon
= &s_AdvancedIcons
[s_AdvancedIconCount
];
114 lstrcpynW(pIcon
->szPath
, pszPath
, _countof(pIcon
->szPath
));
115 pIcon
->nIconIndex
= nIconIndex
;
117 // add the icon to the image list
118 ImageList_AddIcon(s_hImageList
, hIconSmall
);
120 // increment the counter
121 nIconID
= s_AdvancedIconCount
;
122 ++s_AdvancedIconCount
;
124 DestroyIcon(hIconSmall
);
126 return nIconID
; // newly-added icon ID
129 // types of Advanced Setting entry
130 typedef enum ADVANCED_ENTRY_TYPE
135 } ADVANCED_ENTRY_TYPE
;
137 // an entry info of Advanced Settings
138 typedef struct ADVANCED_ENTRY
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)
148 HKEY hkeyRoot
; // registry root key
149 WCHAR szRegPath
[MAX_PATH
]; // registry path
150 WCHAR szValueName
[64]; // registry value name
152 DWORD dwCheckedValue
; // checked value
153 DWORD dwUncheckedValue
; // unchecked value
154 DWORD dwDefaultValue
; // defalut value
155 BOOL bHasUncheckedValue
; // If FALSE, UncheckedValue is invalid
157 HTREEITEM hItem
; // for TreeView
158 BOOL bGrayed
; // disabled?
159 BOOL bChecked
; // checked?
160 } ADVANCED_ENTRY
, *PADVANCED_ENTRY
;
162 // definition of advanced entries
163 static ADVANCED_ENTRY
* s_Advanced
= NULL
;
164 static INT s_AdvancedCount
= 0;
167 Create24BppBitmap(HDC hDC
, INT cx
, INT cy
)
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
;
180 HBITMAP hbm
= CreateDIBSection(hDC
, &bi
, DIB_RGB_COLORS
, &pvBits
, NULL
, 0);
184 static HBITMAP
BitmapFromIcon(HICON hIcon
, INT cx
, INT cy
)
186 HDC hDC
= CreateCompatibleDC(NULL
);
190 HBITMAP hbm
= Create24BppBitmap(hDC
, cx
, cy
);
197 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
199 RECT rc
= { 0, 0, cx
, cy
};
200 FillRect(hDC
, &rc
, HBRUSH(COLOR_3DFACE
+ 1));
203 DrawIconEx(hDC
, 0, 0, hIcon
, cx
, cy
, 0, NULL
, DI_NORMAL
);
206 SelectObject(hDC
, hbmOld
);
213 CreateCheckImage(HDC hDC
, BOOL bCheck
, BOOL bEnabled
= TRUE
)
215 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
216 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
218 HBITMAP hbm
= Create24BppBitmap(hDC
, cxSmallIcon
, cySmallIcon
);
220 return NULL
; // failure
223 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
225 InflateRect(&BoxRect
, -1, -1);
227 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
229 UINT uState
= DFCS_BUTTONCHECK
| DFCS_FLAT
| DFCS_MONO
;
231 uState
|= DFCS_CHECKED
;
233 uState
|= DFCS_INACTIVE
;
234 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
236 SelectObject(hDC
, hbmOld
);
238 return hbm
; // success
242 CreateCheckMask(HDC hDC
)
244 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
245 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
247 HBITMAP hbm
= CreateBitmap(cxSmallIcon
, cySmallIcon
, 1, 1, NULL
);
249 return NULL
; // failure
252 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
254 InflateRect(&BoxRect
, -1, -1);
256 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
258 FillRect(hDC
, &Rect
, HBRUSH(GetStockObject(WHITE_BRUSH
)));
259 FillRect(hDC
, &BoxRect
, HBRUSH(GetStockObject(BLACK_BRUSH
)));
261 SelectObject(hDC
, hbmOld
);
263 return hbm
; // success
267 CreateRadioImage(HDC hDC
, BOOL bCheck
, BOOL bEnabled
= TRUE
)
269 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
270 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
272 HBITMAP hbm
= Create24BppBitmap(hDC
, cxSmallIcon
, cySmallIcon
);
274 return NULL
; // failure
277 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
279 InflateRect(&BoxRect
, -1, -1);
281 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
283 UINT uState
= DFCS_BUTTONRADIOIMAGE
| DFCS_FLAT
| DFCS_MONO
;
285 uState
|= DFCS_CHECKED
;
287 uState
|= DFCS_INACTIVE
;
288 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
290 SelectObject(hDC
, hbmOld
);
292 return hbm
; // success
296 CreateRadioMask(HDC hDC
)
298 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
299 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
301 HBITMAP hbm
= CreateBitmap(cxSmallIcon
, cySmallIcon
, 1, 1, NULL
);
303 return NULL
; // failure
306 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
308 InflateRect(&BoxRect
, -1, -1);
310 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
312 FillRect(hDC
, &Rect
, HBRUSH(GetStockObject(WHITE_BRUSH
)));
313 UINT uState
= DFCS_BUTTONRADIOMASK
| DFCS_FLAT
| DFCS_MONO
;
314 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
316 SelectObject(hDC
, hbmOld
);
318 return hbm
; // success
322 CreateTreeImageList(VOID
)
324 HIMAGELIST hImageList
;
325 hImageList
= ImageList_Create(16, 16, ILC_COLOR24
| ILC_MASK
, 9, 1);
326 if (hImageList
== NULL
)
327 return NULL
; // failure
332 free(s_AdvancedIcons
);
333 s_AdvancedIcons
= NULL
;
335 s_AdvancedIconCount
= 0;
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
344 s_AdvancedIconCount
= PREDEFINED_ICON_COUNT
;
345 s_AdvancedIcons
= pAllocated
;
347 // add the predefined icons
349 HDC hDC
= CreateCompatibleDC(NULL
);
350 HBITMAP hbmMask
= CreateCheckMask(hDC
);
352 HBITMAP hbmChecked
, hbmUnchecked
;
354 hbmChecked
= CreateCheckImage(hDC
, TRUE
);
355 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
356 DeleteObject(hbmChecked
);
358 hbmUnchecked
= CreateCheckImage(hDC
, FALSE
);
359 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
360 DeleteObject(hbmUnchecked
);
362 hbmChecked
= CreateCheckImage(hDC
, TRUE
, FALSE
);
363 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
364 DeleteObject(hbmChecked
);
366 hbmUnchecked
= CreateCheckImage(hDC
, FALSE
, FALSE
);
367 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
368 DeleteObject(hbmUnchecked
);
370 DeleteObject(hbmMask
);
371 hbmMask
= CreateRadioMask(hDC
);
373 hbmChecked
= CreateRadioImage(hDC
, TRUE
);
374 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
375 DeleteObject(hbmChecked
);
377 hbmUnchecked
= CreateRadioImage(hDC
, FALSE
);
378 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
379 DeleteObject(hbmUnchecked
);
381 hbmChecked
= CreateRadioImage(hDC
, TRUE
, FALSE
);
382 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
383 DeleteObject(hbmChecked
);
385 hbmUnchecked
= CreateRadioImage(hDC
, FALSE
, FALSE
);
386 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
387 DeleteObject(hbmUnchecked
);
389 DeleteObject(hbmMask
);
394 static ADVANCED_ENTRY
*
395 Advanced_GetItem(DWORD dwID
)
397 if (dwID
== DWORD(-1))
400 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
402 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
403 if (pEntry
->dwID
== dwID
)
406 return NULL
; // failure
410 Advanced_GetImage(ADVANCED_ENTRY
*pEntry
)
412 switch (pEntry
->dwType
)
415 return pEntry
->nIconID
;
417 case AETYPE_CHECKBOX
:
420 if (pEntry
->bChecked
)
421 return I_CHECKED_DISABLED
;
423 return I_UNCHECKED_DISABLED
;
427 if (pEntry
->bChecked
)
436 if (pEntry
->bChecked
)
437 return I_RADIO_CHECKED_DISABLED
;
439 return I_RADIO_UNCHECKED_DISABLED
;
443 if (pEntry
->bChecked
)
444 return I_RADIO_CHECKED
;
446 return I_RADIO_UNCHECKED
;
449 return -1; // failure
453 Advanced_InsertEntry(HWND hwndTreeView
, ADVANCED_ENTRY
*pEntry
)
455 ADVANCED_ENTRY
*pParent
= Advanced_GetItem(pEntry
->dwParentID
);
456 HTREEITEM hParent
= TVI_ROOT
;
458 hParent
= pParent
->hItem
;
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
;
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
);
475 Advanced_InsertAll(HWND hwndTreeView
)
477 TreeView_DeleteAllItems(hwndTreeView
);
479 // insert the entries
480 ADVANCED_ENTRY
*pEntry
;
481 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
483 pEntry
= &s_Advanced
[i
];
484 Advanced_InsertEntry(hwndTreeView
, pEntry
);
488 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
490 pEntry
= &s_Advanced
[i
];
491 if (pEntry
->dwType
== AETYPE_GROUP
)
493 TreeView_Expand(hwndTreeView
, pEntry
->hItem
, TVE_EXPAND
);
499 Advanced_LoadTree(HKEY hKey
, LPCWSTR pszKeyName
, DWORD dwParentID
)
502 WCHAR szKeyName
[64], szText
[MAX_PATH
], *pch
;
504 ADVANCED_ENTRY
*pAllocated
;
507 Size
= (s_AdvancedCount
+ 1) * sizeof(ADVANCED_ENTRY
);
508 pAllocated
= (ADVANCED_ENTRY
*)realloc(s_Advanced
, Size
);
509 if (pAllocated
== NULL
)
510 return FALSE
; // failure
512 s_Advanced
= pAllocated
;
514 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[s_AdvancedCount
];
516 // dwID, dwParentID, szKeyName
517 pEntry
->dwID
= s_AdvancedCount
;
518 pEntry
->dwParentID
= dwParentID
;
519 lstrcpynW(pEntry
->szKeyName
, pszKeyName
, _countof(pEntry
->szKeyName
));
522 pEntry
->szText
[0] = 0;
523 pEntry
->dwResourceID
= 0;
525 Size
= sizeof(szText
);
526 RegQueryValueExW(hKey
, L
"Text", NULL
, NULL
, LPBYTE(szText
), &Size
);
527 if (szText
[0] == L
'@')
529 pch
= wcsrchr(szText
, L
',');
533 dwIndex
= abs(_wtoi(pch
+ 1));
534 pEntry
->dwResourceID
= dwIndex
;
536 HINSTANCE hInst
= LoadLibraryW(&szText
[1]);
537 LoadStringW(hInst
, dwIndex
, szText
, _countof(szText
));
542 pEntry
->dwResourceID
= DWORD(-1);
544 lstrcpynW(pEntry
->szText
, szText
, _countof(pEntry
->szText
));
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
;
556 return FALSE
; // failure
558 pEntry
->nIconID
= -1;
559 if (pEntry
->dwType
== AETYPE_GROUP
)
563 Size
= sizeof(szText
);
565 RegQueryValueExW(hKey
, L
"Bitmap", NULL
, NULL
, LPBYTE(szText
), &Size
);
567 WCHAR szExpanded
[MAX_PATH
];
568 ExpandEnvironmentStringsW(szText
, szExpanded
, _countof(szExpanded
));
569 pch
= wcsrchr(szExpanded
, L
',');
573 nIconIndex
= abs(_wtoi(pch
+ 1));
575 pEntry
->nIconID
= Advanced_AddIcon(szExpanded
, nIconIndex
);
578 if (pEntry
->dwType
== AETYPE_GROUP
)
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
;
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
);
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
));
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
));
612 Size
= sizeof(Value
);
614 RegQueryValueExW(hKey
, L
"CheckedValue", NULL
, NULL
, LPBYTE(&Value
), &Size
);
615 pEntry
->dwCheckedValue
= Value
;
618 Size
= sizeof(Value
);
620 pEntry
->bHasUncheckedValue
= TRUE
;
621 if (RegQueryValueExW(hKey
, L
"UncheckedValue", NULL
,
622 NULL
, LPBYTE(&Value
), &Size
) != ERROR_SUCCESS
)
624 pEntry
->bHasUncheckedValue
= FALSE
;
626 pEntry
->dwUncheckedValue
= Value
;
629 Size
= sizeof(Value
);
631 RegQueryValueExW(hKey
, L
"DefaultValue", NULL
, NULL
, LPBYTE(&Value
), &Size
);
632 pEntry
->dwDefaultValue
= Value
;
635 pEntry
->hItem
= NULL
;
639 Value
= pEntry
->dwDefaultValue
;
640 pEntry
->bGrayed
= TRUE
;
641 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
, 0,
642 KEY_READ
, &hkeyTarget
) == ERROR_SUCCESS
)
644 Size
= sizeof(Value
);
645 if (RegQueryValueExW(hkeyTarget
, pEntry
->szValueName
, NULL
, NULL
,
646 LPBYTE(&Value
), &Size
) == ERROR_SUCCESS
)
648 pEntry
->bGrayed
= FALSE
;
650 RegCloseKey(hkeyTarget
);
652 pEntry
->bChecked
= (Value
== pEntry
->dwCheckedValue
);
655 // Grayed (ReactOS extension)
656 Size
= sizeof(Value
);
658 RegQueryValueExW(hKey
, L
"Grayed", NULL
, NULL
, LPBYTE(&Value
), &Size
);
659 if (!pEntry
->bGrayed
)
660 pEntry
->bGrayed
= Value
;
662 BOOL bIsGroup
= (pEntry
->dwType
== AETYPE_GROUP
);
663 dwParentID
= pEntry
->dwID
;
667 return TRUE
; // success
671 while (RegEnumKeyW(hKey
, dwIndex
, szKeyName
,
672 _countof(szKeyName
)) == ERROR_SUCCESS
)
675 if (RegOpenKeyExW(hKey
, szKeyName
, 0, KEY_READ
,
676 &hkeyChild
) != ERROR_SUCCESS
)
682 Advanced_LoadTree(hkeyChild
, szKeyName
, dwParentID
);
683 RegCloseKey(hkeyChild
);
688 return TRUE
; // success
692 Advanced_LoadAll(VOID
)
694 static const WCHAR s_szAdvanced
[] =
695 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
697 // free if already existed
706 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, s_szAdvanced
, 0,
707 KEY_READ
, &hKey
) != ERROR_SUCCESS
)
709 return FALSE
; // failure
715 while (RegEnumKeyW(hKey
, dwIndex
, szKeyName
,
716 _countof(szKeyName
)) == ERROR_SUCCESS
)
719 if (RegOpenKeyExW(hKey
, szKeyName
, 0, KEY_READ
,
720 &hkeyChild
) != ERROR_SUCCESS
)
726 Advanced_LoadTree(hkeyChild
, szKeyName
, DWORD(-1));
727 RegCloseKey(hkeyChild
);
734 return TRUE
; // success
738 Advanced_Compare(const void *x
, const void *y
)
740 ADVANCED_ENTRY
*pEntry1
= (ADVANCED_ENTRY
*)x
;
741 ADVANCED_ENTRY
*pEntry2
= (ADVANCED_ENTRY
*)y
;
743 DWORD dwParentID1
= pEntry1
->dwParentID
;
744 DWORD dwParentID2
= pEntry2
->dwParentID
;
746 if (dwParentID1
== dwParentID2
)
747 return lstrcmpi(pEntry1
->szText
, pEntry2
->szText
);
750 const UINT MAX_DEPTH
= 32;
751 ADVANCED_ENTRY
*pArray1
[MAX_DEPTH
];
752 ADVANCED_ENTRY
*pArray2
[MAX_DEPTH
];
754 // Make ancestor lists
755 for (i
= m
= n
= 0; i
< MAX_DEPTH
; ++i
)
757 ADVANCED_ENTRY
*pParent1
= Advanced_GetItem(dwParentID1
);
758 ADVANCED_ENTRY
*pParent2
= Advanced_GetItem(dwParentID2
);
759 if (!pParent1
&& !pParent2
)
764 pArray1
[m
++] = pParent1
;
765 dwParentID1
= pParent1
->dwParentID
;
769 pArray2
[n
++] = pParent2
;
770 dwParentID2
= pParent2
->dwParentID
;
775 for (i
= 0; i
< k
; ++i
)
777 INT nCompare
= lstrcmpi(pArray1
[m
- i
- 1]->szText
, pArray2
[n
- i
- 1]->szText
);
788 return lstrcmpi(pEntry1
->szText
, pEntry2
->szText
);
792 Advanced_SortAll(VOID
)
794 qsort(s_Advanced
, s_AdvancedCount
, sizeof(ADVANCED_ENTRY
), Advanced_Compare
);
797 EXTERN_C HPSXA WINAPI
SHCreatePropSheetExtArrayEx(HKEY hKey
, LPCWSTR pszSubKey
, UINT max_iface
, IDataObject
*pDataObj
);
800 UpdateGeneralIcons(HWND hDlg
)
802 HWND hwndTaskIcon
, hwndFolderIcon
, hwndClickIcon
;
803 HICON hTaskIcon
= NULL
, hFolderIcon
= NULL
, hClickIcon
= NULL
;
804 LPTSTR lpTaskIconName
= NULL
, lpFolderIconName
= NULL
, lpClickIconName
= NULL
;
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
);
814 hTaskIcon
= (HICON
)LoadImage(shell32_hInstance
,
822 hwndTaskIcon
= GetDlgItem(hDlg
,
823 IDC_FOLDER_OPTIONS_TASKICON
);
826 SendMessage(hwndTaskIcon
,
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
);
840 if (lpFolderIconName
)
842 hFolderIcon
= (HICON
)LoadImage(shell32_hInstance
,
850 hwndFolderIcon
= GetDlgItem(hDlg
,
851 IDC_FOLDER_OPTIONS_FOLDERICON
);
854 SendMessage(hwndFolderIcon
,
857 (LPARAM
)hFolderIcon
);
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
);
870 hClickIcon
= (HICON
)LoadImage(shell32_hInstance
,
878 hwndClickIcon
= GetDlgItem(hDlg
,
879 IDC_FOLDER_OPTIONS_CLICKICON
);
882 SendMessage(hwndClickIcon
,
892 DeleteObject(hTaskIcon
);
894 DeleteObject(hFolderIcon
);
896 DeleteObject(hClickIcon
);
903 FolderOptionsGeneralDlg(
917 switch (LOWORD(wParam
))
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
)
927 UpdateGeneralIcons(hwndDlg
);
929 /* Enable the 'Apply' button */
930 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
938 LPNMHDR pnmh
= (LPNMHDR
)lParam
;
961 ViewDlg_OnInitDialog(HWND hwndDlg
)
963 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
965 s_hImageList
= CreateTreeImageList();
966 TreeView_SetImageList(hwndTreeView
, s_hImageList
, TVSIL_NORMAL
);
970 Advanced_InsertAll(hwndTreeView
);
972 return TRUE
; // set focus
976 ViewDlg_ToggleCheckItem(HWND hwndDlg
, HTREEITEM hItem
)
978 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
983 ZeroMemory(&Item
, sizeof(Item
));
984 Item
.mask
= TVIF_HANDLE
| TVIF_IMAGE
| TVIF_PARAM
;
986 if (!TreeView_GetItem(hwndTreeView
, &Item
))
987 return FALSE
; // no such item
989 ADVANCED_ENTRY
*pEntry
= Advanced_GetItem(Item
.lParam
);
991 return FALSE
; // no such item
993 return FALSE
; // disabled
996 Item
.mask
= TVIF_HANDLE
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
997 switch (pEntry
->dwType
)
999 case AETYPE_CHECKBOX
:
1000 pEntry
->bChecked
= !pEntry
->bChecked
;
1004 // reset all the entries of the same parent
1005 for (i
= 0; i
< s_AdvancedCount
; ++i
)
1007 ADVANCED_ENTRY
*pEntry2
= &s_Advanced
[i
];
1008 if (pEntry
->dwParentID
== pEntry2
->dwParentID
)
1010 pEntry2
->bChecked
= FALSE
;
1012 Item
.hItem
= pEntry2
->hItem
;
1013 INT iImage
= Advanced_GetImage(pEntry2
);
1014 Item
.iImage
= Item
.iSelectedImage
= iImage
;
1015 TreeView_SetItem(hwndTreeView
, &Item
);
1018 pEntry
->bChecked
= TRUE
;
1022 return FALSE
; // failure
1024 Item
.iImage
= Item
.iSelectedImage
= Advanced_GetImage(pEntry
);
1026 TreeView_SetItem(hwndTreeView
, &Item
);
1030 TreeView_GetItemRect(hwndTreeView
, hItem
, &rcItem
, FALSE
);
1031 InvalidateRect(hwndTreeView
, &rcItem
, TRUE
);
1032 return TRUE
; // success
1036 ViewDlg_OnTreeViewClick(HWND hwndDlg
)
1038 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
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
);
1049 // toggle the check mark if possible
1050 if (ViewDlg_ToggleCheckItem(hwndDlg
, hItem
))
1052 // property sheet was changed
1053 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1058 ViewDlg_OnTreeViewKeyDown(HWND hwndDlg
, TV_KEYDOWN
*KeyDown
)
1060 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
1062 if (KeyDown
->wVKey
== VK_SPACE
)
1064 // [Space] key was pressed
1065 HTREEITEM hItem
= TreeView_GetSelection(hwndTreeView
);
1066 if (ViewDlg_ToggleCheckItem(hwndDlg
, hItem
))
1068 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1074 ViewDlg_OnTreeCustomDraw(HWND hwndDlg
, NMTVCUSTOMDRAW
*Draw
)
1076 NMCUSTOMDRAW
& nmcd
= Draw
->nmcd
;
1077 switch (nmcd
.dwDrawStage
)
1080 return CDRF_NOTIFYITEMDRAW
; // for CDDS_ITEMPREPAINT
1082 case CDDS_ITEMPREPAINT
:
1083 if (!(nmcd
.uItemState
& CDIS_SELECTED
)) // not selected
1085 LPARAM lParam
= nmcd
.lItemlParam
;
1086 ADVANCED_ENTRY
*pEntry
= Advanced_GetItem(lParam
);
1087 if (pEntry
&& pEntry
->bGrayed
) // disabled
1090 Draw
->clrText
= GetSysColor(COLOR_GRAYTEXT
);
1091 Draw
->clrTextBk
= GetSysColor(COLOR_WINDOW
);
1092 return CDRF_NEWFONT
;
1100 return CDRF_DODEFAULT
;
1104 Advanced_RestoreDefaults(HWND hwndDlg
)
1106 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
1108 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
1110 // ignore if the type is group
1111 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
1112 if (pEntry
->dwType
== AETYPE_GROUP
)
1115 // set default value on registry
1117 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
,
1118 0, KEY_WRITE
, &hKey
) != ERROR_SUCCESS
)
1122 RegSetValueExW(hKey
, pEntry
->szValueName
, 0, REG_DWORD
,
1123 LPBYTE(pEntry
->dwDefaultValue
), sizeof(DWORD
));
1126 // update check status
1127 pEntry
->bChecked
= (pEntry
->dwCheckedValue
== pEntry
->dwDefaultValue
);
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
);
1138 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1141 /* FIXME: These macros should not be defined here */
1142 #ifndef SSF_SHOWSUPERHIDDEN
1143 #define SSF_SHOWSUPERHIDDEN 0x00040000
1145 #ifndef SSF_SEPPROCESS
1146 #define SSF_SEPPROCESS 0x00080000
1150 ScanAdvancedSettings(SHELLSTATE
*pSS
, DWORD
*pdwMask
)
1152 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
1154 const ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
1155 if (pEntry
->dwType
== AETYPE_GROUP
|| pEntry
->bGrayed
)
1158 BOOL bChecked
= pEntry
->bChecked
;
1160 // FIXME: Add more items
1161 if (lstrcmpiW(pEntry
->szKeyName
, L
"SuperHidden") == 0)
1163 pSS
->fShowSuperHidden
= !bChecked
? 1 : 0;
1164 *pdwMask
|= SSF_SHOWSUPERHIDDEN
;
1167 if (lstrcmpiW(pEntry
->szKeyName
, L
"DesktopProcess") == 0)
1169 pSS
->fSepProcess
= bChecked
? 1 : 0;
1170 *pdwMask
|= SSF_SEPPROCESS
;
1173 if (lstrcmpiW(pEntry
->szKeyName
, L
"SHOWALL") == 0)
1175 pSS
->fShowAllObjects
= !bChecked
? 1 : 0;
1176 *pdwMask
|= SSF_SHOWALLOBJECTS
;
1179 if (lstrcmpiW(pEntry
->szKeyName
, L
"HideFileExt") == 0)
1181 pSS
->fShowExtensions
= !bChecked
? 1 : 0;
1182 *pdwMask
|= SSF_SHOWEXTENSIONS
;
1185 if (lstrcmpiW(pEntry
->szKeyName
, L
"ShowCompColor") == 0)
1187 pSS
->fShowCompColor
= bChecked
? 1 : 0;
1188 *pdwMask
|= SSF_SHOWCOMPCOLOR
;
1191 if (lstrcmpiW(pEntry
->szKeyName
, L
"ShowInfoTip") == 0)
1193 pSS
->fShowInfoTip
= bChecked
? 1 : 0;
1194 *pdwMask
|= SSF_SHOWINFOTIP
;
1201 VOID WINAPI
SHGetSetSettings(LPSHELLSTATE lpss
, DWORD dwMask
, BOOL bSet
);
1203 static BOOL CALLBACK
RefreshBrowsersCallback (HWND hWnd
, LPARAM msg
)
1205 WCHAR ClassName
[100];
1206 if (GetClassName(hWnd
, ClassName
, 100))
1208 if (!wcscmp(ClassName
, L
"Progman") ||
1209 !wcscmp(ClassName
, L
"CabinetWClass") ||
1210 !wcscmp(ClassName
, L
"ExploreWClass"))
1212 PostMessage(hWnd
, WM_COMMAND
, FCIDM_DESKBROWSER_REFRESH
, 0);
1219 ViewDlg_Apply(HWND hwndDlg
)
1221 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
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
)
1228 // open the registry key
1230 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
, 0,
1231 KEY_WRITE
, &hkeyTarget
) != ERROR_SUCCESS
)
1236 // checked or unchecked?
1237 DWORD dwValue
, dwSize
;
1238 if (pEntry
->bChecked
)
1240 dwValue
= pEntry
->dwCheckedValue
;
1244 if (pEntry
->bHasUncheckedValue
)
1246 dwValue
= pEntry
->dwUncheckedValue
;
1250 // there is no unchecked value
1251 RegCloseKey(hkeyTarget
);
1257 dwSize
= sizeof(dwValue
);
1258 RegSetValueExW(hkeyTarget
, pEntry
->szValueName
, 0, REG_DWORD
,
1259 LPBYTE(&dwValue
), dwSize
);
1262 RegCloseKey(hkeyTarget
);
1265 // scan advanced settings for user's settings
1267 SHELLSTATE ShellState
;
1268 ZeroMemory(&ShellState
, sizeof(ShellState
));
1269 ScanAdvancedSettings(&ShellState
, &dwMask
);
1271 // update user's settings
1272 SHGetSetSettings(&ShellState
, dwMask
, TRUE
);
1275 SendMessage(HWND_BROADCAST
, WM_WININICHANGE
, 0, 0);
1277 EnumWindows(RefreshBrowsersCallback
, NULL
);
1281 FolderOptionsViewDlg(
1288 NMTVCUSTOMDRAW
*Draw
;
1293 return ViewDlg_OnInitDialog(hwndDlg
);
1296 switch (LOWORD(wParam
))
1298 case 14004: // Restore Defaults
1299 Advanced_RestoreDefaults(hwndDlg
);
1305 switch (LPNMHDR(lParam
)->code
)
1307 case NM_CLICK
: // clicked on treeview
1308 ViewDlg_OnTreeViewClick(hwndDlg
);
1311 case NM_CUSTOMDRAW
: // custom draw (for graying)
1312 Draw
= (NMTVCUSTOMDRAW
*)lParam
;
1313 Result
= ViewDlg_OnTreeCustomDraw(hwndDlg
, Draw
);
1314 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, Result
);
1317 case TVN_KEYDOWN
: // key is down
1318 ViewDlg_OnTreeViewKeyDown(hwndDlg
, (TV_KEYDOWN
*)lParam
);
1321 case PSN_APPLY
: // [Apply] is clicked
1322 ViewDlg_Apply(hwndDlg
);
1336 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
1342 int columnSize
= 140;
1345 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
1347 /* default to english */
1348 wcscpy(szName
, L
"Extensions");
1351 /* make sure its null terminated */
1352 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
1354 GetClientRect(hDlgCtrl
, &clientRect
);
1355 ZeroMemory(&col
, sizeof(LV_COLUMN
));
1356 columnSize
= 140; //FIXME
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
);
1365 if (!LoadStringW(shell32_hInstance
, IDS_FILE_TYPES
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
1367 /* default to english */
1368 wcscpy(szName
, L
"File Types");
1369 ERR("Failed to load localized string!\n");
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
);
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
);
1385 DeleteExt(HWND hwndDlg
, LPCWSTR pszExt
)
1387 if (*pszExt
!= L
'.')
1392 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, pszExt
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
1395 // query "extfile" key name
1396 WCHAR szValue
[64] = { 0 };
1397 DWORD cbValue
= sizeof(szValue
);
1398 RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, LPBYTE(szValue
), &cbValue
);
1401 // delete "extfile" key (if any)
1403 SHDeleteKeyW(HKEY_CLASSES_ROOT
, szValue
);
1405 // delete ".ext" key
1406 return SHDeleteKeyW(HKEY_CLASSES_ROOT
, pszExt
) == ERROR_SUCCESS
;
1410 DoExtractIcon(PFOLDER_FILE_TYPE_ENTRY Entry
, LPCWSTR IconPath
,
1411 INT iIndex
= 0, BOOL bSmall
= FALSE
)
1417 // A negative value will be interpreted as a negated resource ID.
1421 HINSTANCE hDLL
= LoadLibraryExW(IconPath
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
1424 cx
= GetSystemMetrics(SM_CXSMICON
);
1425 cy
= GetSystemMetrics(SM_CYSMICON
);
1429 cx
= GetSystemMetrics(SM_CXICON
);
1430 cy
= GetSystemMetrics(SM_CYICON
);
1432 hIcon
= HICON(LoadImageW(hDLL
, MAKEINTRESOURCEW(iIndex
), IMAGE_ICON
,
1438 // A positive value is icon index.
1440 ExtractIconExW(IconPath
, iIndex
, NULL
, &hIcon
, 1);
1442 ExtractIconExW(IconPath
, iIndex
, &hIcon
, NULL
, 1);
1448 DoFileTypeIconLocation(PFOLDER_FILE_TYPE_ENTRY Entry
, LPCWSTR IconLocation
)
1450 // Expand the REG_EXPAND_SZ string by environment variables
1451 WCHAR szLocation
[MAX_PATH
+ 32];
1452 if (!ExpandEnvironmentStringsW(IconLocation
, szLocation
, _countof(szLocation
)))
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
);
1464 GetFileTypeIconsEx(PFOLDER_FILE_TYPE_ENTRY Entry
, LPCWSTR IconLocation
)
1466 Entry
->hIconLarge
= Entry
->hIconSmall
= NULL
;
1468 if (lstrcmpiW(Entry
->FileExtension
, L
".exe") == 0 ||
1469 lstrcmpiW(Entry
->FileExtension
, L
".scr") == 0)
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
;
1478 else if (lstrcmpW(IconLocation
, L
"%1") == 0)
1480 return FALSE
; // self icon
1484 DoFileTypeIconLocation(Entry
, IconLocation
);
1487 return Entry
->hIconLarge
&& Entry
->hIconSmall
;
1491 GetFileTypeIconsByKey(HKEY hKey
, PFOLDER_FILE_TYPE_ENTRY Entry
)
1493 Entry
->hIconLarge
= Entry
->hIconSmall
= NULL
;
1495 // Open the "DefaultIcon" registry key
1497 LONG nResult
= RegOpenKeyExW(hKey
, L
"DefaultIcon", 0, KEY_READ
, &hDefIconKey
);
1498 if (nResult
!= ERROR_SUCCESS
)
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
);
1506 RegCloseKey(hDefIconKey
);
1508 if (nResult
!= ERROR_SUCCESS
|| szLocation
[0] == 0)
1511 return GetFileTypeIconsEx(Entry
, szLocation
);
1515 QueryFileDescription(LPCWSTR ProgramPath
, LPWSTR pszName
, INT cchName
)
1517 SHFILEINFOW FileInfo
= { 0 };
1518 if (SHGetFileInfoW(ProgramPath
, 0, &FileInfo
, sizeof(FileInfo
), SHGFI_DISPLAYNAME
))
1520 StringCchCopyW(pszName
, cchName
, FileInfo
.szDisplayName
);
1524 return !!GetFileTitleW(ProgramPath
, pszName
, cchName
);
1528 SetFileTypeEntryDefaultIcon(PFOLDER_FILE_TYPE_ENTRY Entry
)
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
;
1540 InsertFileType(HWND hListView
, LPCWSTR szName
, INT iItem
, LPCWSTR szFile
)
1542 PFOLDER_FILE_TYPE_ENTRY Entry
;
1548 if (szName
[0] != L
'.')
1550 /* FIXME handle URL protocol handlers */
1554 // get imagelists of listview
1555 HIMAGELIST himlLarge
= ListView_GetImageList(hListView
, LVSIL_NORMAL
);
1556 HIMAGELIST himlSmall
= ListView_GetImageList(hListView
, LVSIL_SMALL
);
1558 /* allocate file type entry */
1559 Entry
= (PFOLDER_FILE_TYPE_ENTRY
)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY
));
1564 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szName
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
1566 HeapFree(GetProcessHeap(), 0, Entry
);
1570 /* FIXME check for duplicates */
1572 /* query for the default key */
1573 dwSize
= sizeof(Entry
->ClassKey
);
1574 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->ClassKey
, &dwSize
) != ERROR_SUCCESS
)
1576 /* no link available */
1577 Entry
->ClassKey
[0] = 0;
1580 Entry
->ClassName
[0] = 0;
1581 if (Entry
->ClassKey
[0])
1584 /* try open linked key */
1585 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, Entry
->ClassKey
, 0, KEY_READ
, &hTemp
) == ERROR_SUCCESS
)
1587 DWORD dwSize
= sizeof(Entry
->ClassName
);
1588 RegQueryValueExW(hTemp
, NULL
, NULL
, NULL
, LPBYTE(Entry
->ClassName
), &dwSize
);
1590 /* use linked key */
1596 /* read friendly type name */
1597 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", Entry
->FileDescription
, sizeof(Entry
->FileDescription
), NULL
, 0, NULL
) != ERROR_SUCCESS
)
1599 /* read file description */
1600 dwSize
= sizeof(Entry
->FileDescription
);
1601 Entry
->FileDescription
[0] = 0;
1603 /* read default key */
1604 RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->FileDescription
, &dwSize
);
1607 /* Read the EditFlags value */
1608 Entry
->EditFlags
= 0;
1609 if (!RegQueryValueExW(hKey
, L
"EditFlags", NULL
, &dwType
, NULL
, &dwSize
))
1611 if ((dwType
== REG_DWORD
|| dwType
== REG_BINARY
) && dwSize
== sizeof(DWORD
))
1612 RegQueryValueExW(hKey
, L
"EditFlags", NULL
, NULL
, (LPBYTE
)&Entry
->EditFlags
, &dwSize
);
1615 /* convert extension to upper case */
1616 wcscpy(Entry
->FileExtension
, szName
);
1617 _wcsupr(Entry
->FileExtension
);
1620 if (!GetFileTypeIconsByKey(hKey
, Entry
))
1623 SetFileTypeEntryDefaultIcon(Entry
);
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
))
1634 QueryFileDescription(Entry
->ProgramPath
, Entry
->AppName
, _countof(Entry
->AppName
));
1638 Entry
->ProgramPath
[0] = Entry
->AppName
[0] = 0;
1641 // add icon to imagelist
1642 INT iLargeImage
= -1, iSmallImage
= -1;
1643 if (Entry
->hIconLarge
&& Entry
->hIconSmall
)
1645 iLargeImage
= ImageList_AddIcon(himlLarge
, Entry
->hIconLarge
);
1646 iSmallImage
= ImageList_AddIcon(himlSmall
, Entry
->hIconSmall
);
1647 ASSERT(iLargeImage
== iSmallImage
);
1650 /* Do not add excluded entries */
1651 if (Entry
->EditFlags
& 0x00000001) //FTA_Exclude
1653 DestroyIcon(Entry
->hIconLarge
);
1654 DestroyIcon(Entry
->hIconSmall
);
1655 HeapFree(GetProcessHeap(), 0, Entry
);
1659 if (!Entry
->FileDescription
[0])
1661 /* construct default 'FileExtensionFile' by formatting the uppercase extension
1662 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
1664 StringCchPrintf(Entry
->FileDescription
, _countof(Entry
->FileDescription
), szFile
, &Entry
->FileExtension
[1]);
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
);
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
);
1689 ListViewCompareProc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
1691 PFOLDER_FILE_TYPE_ENTRY Entry1
, Entry2
;
1694 Entry1
= (PFOLDER_FILE_TYPE_ENTRY
)lParam1
;
1695 Entry2
= (PFOLDER_FILE_TYPE_ENTRY
)lParam2
;
1697 x
= wcsicmp(Entry1
->FileExtension
, Entry2
->FileExtension
);
1701 return wcsicmp(Entry1
->FileDescription
, Entry2
->FileDescription
);
1705 PFOLDER_FILE_TYPE_ENTRY
1706 InitializeFileTypesListCtrl(HWND hwndDlg
)
1715 HIMAGELIST himlLarge
, himlSmall
;
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);
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
);
1728 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
1731 if (!LoadStringW(shell32_hInstance
, IDS_FILE_EXT_TYPE
, szFile
, _countof(szFile
)))
1733 /* default to english */
1734 wcscpy(szFile
, L
"%s File");
1736 szFile
[(_countof(szFile
)) - 1] = 0;
1738 dwName
= _countof(szName
);
1740 while (RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
1742 if (InsertFileType(hDlgCtrl
, szName
, iItem
, szFile
))
1744 dwName
= _countof(szName
);
1747 /* Leave if the list is empty */
1752 ListView_SortItems(hDlgCtrl
, ListViewCompareProc
, NULL
);
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
;
1760 ListView_SetItem(hDlgCtrl
, &lvItem
);
1762 lvItem
.mask
= LVIF_PARAM
;
1763 ListView_GetItem(hDlgCtrl
, &lvItem
);
1765 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
1769 PFOLDER_FILE_TYPE_ENTRY
1770 GetListViewEntry(HWND hListView
, INT iItem
= -1)
1774 iItem
= ListView_GetNextItem(hListView
, -1, LVNI_SELECTED
);
1779 LV_ITEMW lvItem
= { LVIF_PARAM
, iItem
};
1780 if (ListView_GetItem(hListView
, &lvItem
))
1781 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
1786 struct NEWEXT_DIALOG
1793 WCHAR szFileType
[64];
1797 NewExtDlg_OnAdvanced(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1799 // If "Advanced" button was clicked, then we shrink or expand the dialog.
1803 GetWindowRect(hwndDlg
, &rc
);
1804 rc
.bottom
= rc
.top
+ (pNewExt
->rcDlg
.bottom
- pNewExt
->rcDlg
.top
);
1806 GetWindowRect(GetDlgItem(hwndDlg
, IDOK
), &rc1
);
1807 MapWindowPoints(NULL
, hwndDlg
, (POINT
*)&rc1
, 2);
1809 GetWindowRect(GetDlgItem(hwndDlg
, IDCANCEL
), &rc2
);
1810 MapWindowPoints(NULL
, hwndDlg
, (POINT
*)&rc2
, 2);
1812 if (pNewExt
->bAdvanced
)
1814 rc1
.top
+= pNewExt
->dy
;
1815 rc1
.bottom
+= pNewExt
->dy
;
1817 rc2
.top
+= pNewExt
->dy
;
1818 rc2
.bottom
+= pNewExt
->dy
;
1820 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_ASSOC
), SW_SHOWNOACTIVATE
);
1821 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), SW_SHOWNOACTIVATE
);
1823 LoadStringW(shell32_hInstance
, IDS_NEWEXT_ADVANCED_LEFT
, szText
, _countof(szText
));
1824 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_ADVANCED
, szText
);
1826 SetFocus(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
));
1830 rc1
.top
-= pNewExt
->dy
;
1831 rc1
.bottom
-= pNewExt
->dy
;
1833 rc2
.top
-= pNewExt
->dy
;
1834 rc2
.bottom
-= pNewExt
->dy
;
1836 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_ASSOC
), SW_HIDE
);
1837 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), SW_HIDE
);
1839 LoadStringW(shell32_hInstance
, IDS_NEWEXT_ADVANCED_RIGHT
, szText
, _countof(szText
));
1840 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_ADVANCED
, szText
);
1842 rc
.bottom
-= pNewExt
->dy
;
1844 LoadStringW(shell32_hInstance
, IDS_NEWEXT_NEW
, szText
, _countof(szText
));
1845 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, szText
);
1848 HDWP hDWP
= BeginDeferWindowPos(3);
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
);
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
);
1859 hDWP
= DeferWindowPos(hDWP
, hwndDlg
, NULL
,
1860 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
1861 SWP_NOACTIVATE
| SWP_NOZORDER
);
1864 EndDeferWindowPos(hDWP
);
1868 NewExtDlg_OnInitDialog(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1872 pNewExt
->bAdvanced
= FALSE
;
1874 GetWindowRect(hwndDlg
, &pNewExt
->rcDlg
);
1877 GetWindowRect(GetDlgItem(hwndDlg
, IDC_NEWEXT_EDIT
), &rc1
);
1878 GetWindowRect(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), &rc2
);
1879 pNewExt
->dy
= rc2
.top
- rc1
.top
;
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);
1885 SendDlgItemMessageW(hwndDlg
, IDC_NEWEXT_EDIT
, EM_SETLIMITTEXT
, _countof(pNewExt
->szExt
) - 1, 0);
1887 NewExtDlg_OnAdvanced(hwndDlg
, pNewExt
);
1892 static LPCWSTR s_pszSpace
= L
" \t\n\r\f\v";
1895 NewExtDlg_OnOK(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1900 GetDlgItemTextW(hwndDlg
, IDC_NEWEXT_EDIT
, pNewExt
->szExt
, _countof(pNewExt
->szExt
));
1901 StrTrimW(pNewExt
->szExt
, s_pszSpace
);
1902 CharUpperW(pNewExt
->szExt
);
1904 GetDlgItemTextW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, pNewExt
->szFileType
, _countof(pNewExt
->szFileType
));
1905 StrTrimW(pNewExt
->szFileType
, s_pszSpace
);
1907 if (pNewExt
->szExt
[0] == 0)
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
);
1918 ZeroMemory(&find
, sizeof(find
));
1919 find
.flags
= LVFI_STRING
;
1920 if (pNewExt
->szExt
[0] == L
'.')
1922 find
.psz
= &pNewExt
->szExt
[1];
1926 find
.psz
= pNewExt
->szExt
;
1929 iItem
= ListView_FindItem(pNewExt
->hwndLV
, -1, &find
);
1933 WCHAR szText
[256], szFormat
[256], szTitle
[64], szFileType
[64];
1937 ZeroMemory(&item
, sizeof(item
));
1938 item
.mask
= LVIF_TEXT
;
1939 item
.pszText
= szFileType
;
1940 item
.cchTextMax
= _countof(szFileType
);
1943 ListView_GetItem(pNewExt
->hwndLV
, &item
);
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
);
1951 LoadStringW(shell32_hInstance
, IDS_NEWEXT_EXT_IN_USE
, szTitle
, _countof(szTitle
));
1952 szTitle
[_countof(szTitle
) - 1] = 0;
1954 if (MessageBoxW(hwndDlg
, szText
, szTitle
, MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1959 // Delete the extension
1960 CStringW
strExt(L
".");
1963 DeleteExt(hwndDlg
, strExt
);
1966 ListView_DeleteItem(pNewExt
->hwndLV
, iItem
);
1969 EndDialog(hwndDlg
, IDOK
);
1973 // IDD_NEWEXTENSION dialog
1976 NewExtensionDlgProc(
1982 static NEWEXT_DIALOG
*s_pNewExt
= NULL
;
1987 s_pNewExt
= (NEWEXT_DIALOG
*)lParam
;
1988 NewExtDlg_OnInitDialog(hwndDlg
, s_pNewExt
);
1992 switch (LOWORD(wParam
))
1995 NewExtDlg_OnOK(hwndDlg
, s_pNewExt
);
1999 EndDialog(hwndDlg
, IDCANCEL
);
2002 case IDC_NEWEXT_ADVANCED
:
2003 s_pNewExt
->bAdvanced
= !s_pNewExt
->bAdvanced
;
2004 NewExtDlg_OnAdvanced(hwndDlg
, s_pNewExt
);
2013 FileTypesDlg_AddExt(HWND hwndDlg
, LPCWSTR pszExt
, LPCWSTR pszFileType
)
2017 WCHAR szKey
[13]; // max. "ft4294967295" + "\0"
2020 // Search the next "ft%06u" key name
2023 StringCchPrintfW(szKey
, _countof(szKey
), TEXT("ft%06u"), dwValue
);
2025 nResult
= RegOpenKeyEx(HKEY_CLASSES_ROOT
, szKey
, 0, KEY_READ
, &hKey
);
2026 if (nResult
!= ERROR_SUCCESS
)
2031 } while (dwValue
!= 0);
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
)
2045 // Create the ".ext" key
2047 if (*pszExt
== L
'.')
2049 StringCchPrintfW(szExt
, _countof(szExt
), TEXT(".%s"), pszExt
);
2051 nResult
= RegCreateKeyEx(HKEY_CLASSES_ROOT
, szExt
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
);
2053 if (ERROR_SUCCESS
!= nResult
)
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
);
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]);
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
))
2075 ZeroMemory(&item
, sizeof(item
));
2076 item
.mask
= LVIF_STATE
| LVIF_TEXT
;
2078 item
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
2079 item
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2080 item
.pszText
= &szExt
[1];
2081 ListView_SetItem(hListView
, &item
);
2083 item
.pszText
= szFile
;
2085 ListView_SetItem(hListView
, &item
);
2087 ListView_EnsureVisible(hListView
, iItem
, FALSE
);
2093 FileTypesDlg_RemoveExt(HWND hwndDlg
)
2095 HWND hListView
= GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
);
2097 INT iItem
= ListView_GetNextItem(hListView
, -1, LVNI_SELECTED
);
2103 ListView_GetItemText(hListView
, iItem
, 0, &szExt
[1], _countof(szExt
) - 1);
2106 DeleteExt(hwndDlg
, szExt
);
2107 ListView_DeleteItem(hListView
, iItem
);
2112 FileTypesDlg_OnItemChanging(HWND hwndDlg
, PFOLDER_FILE_TYPE_ENTRY pEntry
)
2115 static HBITMAP s_hbmProgram
= NULL
;
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
);
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
);
2129 // delete previous program image
2132 DeleteObject(s_hbmProgram
);
2133 s_hbmProgram
= NULL
;
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
));
2144 if (pEntry
->AppName
[0])
2145 SetDlgItemTextW(hwndDlg
, IDC_FILETYPES_APPNAME
, pEntry
->AppName
);
2147 SetDlgItemTextW(hwndDlg
, IDC_FILETYPES_APPNAME
, L
"ReactOS");
2149 /* Enable the Delete button */
2150 if (pEntry
->EditFlags
& 0x00000010) // FTA_NoRemove
2151 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILETYPES_DELETE
), FALSE
);
2153 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILETYPES_DELETE
), TRUE
);
2156 struct EDITTYPE_DIALOG
2159 FOLDER_FILE_TYPE_ENTRY
*pEntry
;
2160 CSimpleMap
<CStringW
, CStringW
> CommandLineMap
;
2161 WCHAR szIconPath
[MAX_PATH
];
2163 WCHAR szDefaultVerb
[64];
2167 EditTypeDlg_ReadClass(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
, LPCWSTR ClassKey
)
2171 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, ClassKey
, 0, KEY_READ
, &hClassKey
) != ERROR_SUCCESS
)
2176 if (RegOpenKeyExW(hClassKey
, L
"shell", 0, KEY_READ
, &hShellKey
) != ERROR_SUCCESS
)
2178 RegCloseKey(hClassKey
);
2182 WCHAR DefaultVerb
[64];
2183 DWORD dwSize
= sizeof(DefaultVerb
);
2184 if (RegQueryValueExW(hShellKey
, NULL
, NULL
, NULL
, LPBYTE(DefaultVerb
), &dwSize
) == ERROR_SUCCESS
)
2186 StringCchCopyW(pEditType
->szDefaultVerb
, _countof(pEditType
->szDefaultVerb
), DefaultVerb
);
2190 StringCchCopyW(pEditType
->szDefaultVerb
, _countof(pEditType
->szDefaultVerb
), L
"open");
2193 // enumerate shell verbs
2194 WCHAR szVerbName
[64];
2196 while (RegEnumKeyW(hShellKey
, dwIndex
, szVerbName
, _countof(szVerbName
)) == ERROR_SUCCESS
)
2200 LONG nResult
= RegOpenKeyExW(hShellKey
, szVerbName
, 0, KEY_READ
, &hVerbKey
);
2201 if (nResult
== ERROR_SUCCESS
)
2205 nResult
= RegOpenKeyExW(hVerbKey
, L
"command", 0, KEY_READ
, &hCommandKey
);
2206 if (nResult
== ERROR_SUCCESS
)
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
)
2214 pEditType
->CommandLineMap
.SetAt(szVerbName
, szValue
);
2217 RegCloseKey(hCommandKey
);
2220 RegCloseKey(hVerbKey
);
2222 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_ADDSTRING
, 0, LPARAM(szVerbName
));
2226 RegCloseKey(hShellKey
);
2227 RegCloseKey(hClassKey
);
2233 EditTypeDlg_WriteClass(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
,
2234 LPCWSTR ClassKey
, LPCWSTR ClassName
, INT cchName
)
2236 FOLDER_FILE_TYPE_ENTRY
*pEntry
= pEditType
->pEntry
;
2238 if (ClassKey
[0] == 0)
2241 // create or open class key
2243 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, ClassKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hClassKey
, NULL
) != ERROR_SUCCESS
)
2246 // create "DefaultIcon" key
2247 if (pEntry
->IconPath
[0])
2249 HKEY hDefaultIconKey
;
2250 if (RegCreateKeyExW(hClassKey
, L
"DefaultIcon", 0, NULL
, 0, KEY_WRITE
, NULL
, &hDefaultIconKey
, NULL
) == ERROR_SUCCESS
)
2252 WCHAR szText
[MAX_PATH
];
2253 StringCchPrintfW(szText
, _countof(szText
), L
"%s,%d", pEntry
->IconPath
, pEntry
->nIconIndex
);
2255 // set icon location
2256 DWORD dwSize
= (lstrlenW(szText
) + 1) * sizeof(WCHAR
);
2257 RegSetValueExW(hDefaultIconKey
, NULL
, 0, REG_EXPAND_SZ
, LPBYTE(szText
), dwSize
);
2259 RegCloseKey(hDefaultIconKey
);
2263 // create "shell" key
2265 if (RegCreateKeyExW(hClassKey
, L
"shell", 0, NULL
, 0, KEY_WRITE
, NULL
, &hShellKey
, NULL
) != ERROR_SUCCESS
)
2267 RegCloseKey(hClassKey
);
2271 // delete shell commands
2272 WCHAR szVerbName
[64];
2274 while (RegEnumKeyW(hShellKey
, dwIndex
, szVerbName
, _countof(szVerbName
)) == ERROR_SUCCESS
)
2276 if (pEditType
->CommandLineMap
.FindKey(szVerbName
) == -1)
2278 // doesn't exist in CommandLineMap, then delete it
2279 if (SHDeleteKeyW(hShellKey
, szVerbName
) == ERROR_SUCCESS
)
2287 // set default action
2288 RegSetValueExW(hShellKey
, NULL
, 0, REG_SZ
, LPBYTE(pEditType
->szDefaultVerb
), sizeof(pEditType
->szDefaultVerb
));
2290 // write shell commands
2291 const INT nCount
= pEditType
->CommandLineMap
.GetSize();
2292 for (INT i
= 0; i
< nCount
; ++i
)
2294 CStringW
& key
= pEditType
->CommandLineMap
.GetKeyAt(i
);
2295 CStringW
& value
= pEditType
->CommandLineMap
.GetValueAt(i
);
2299 if (RegCreateKeyExW(hShellKey
, key
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hVerbKey
, NULL
) == ERROR_SUCCESS
)
2301 // create command key
2303 if (RegCreateKeyExW(hVerbKey
, L
"command", 0, NULL
, 0, KEY_WRITE
, NULL
, &hCommandKey
, NULL
) == ERROR_SUCCESS
)
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
);
2309 RegCloseKey(hCommandKey
);
2312 RegCloseKey(hVerbKey
);
2316 // set class name to class key
2317 RegSetValueExW(hClassKey
, NULL
, 0, REG_SZ
, LPBYTE(ClassName
), cchName
);
2319 RegCloseKey(hShellKey
);
2320 RegCloseKey(hClassKey
);
2326 EditTypeDlg_OnInitDialog(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
)
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");
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
);
2339 // is listbox empty?
2340 if (SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_GETCOUNT
, 0, 0) == 0)
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
);
2348 // select first item
2349 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_SETCURSEL
, 0, 0);
2352 EnableWindow(GetDlgItem(hwndDlg
, IDC_EDITTYPE_SAME_WINDOW
), FALSE
);
2358 EditTypeDlg_OnRemove(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
)
2360 // get current selection
2361 INT iItem
= SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_GETCURSEL
, 0, 0);
2362 if (iItem
== LB_ERR
)
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
)
2374 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_GETTEXT
, iItem
, (LPARAM
)szText
);
2375 StrTrimW(szText
, s_pszSpace
);
2378 pEditType
->CommandLineMap
.Remove(szText
);
2379 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_DELETESTRING
, iItem
, 0);
2384 EditTypeDlg_UpdateEntryIcon(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
, LPCWSTR IconPath
, INT IconIndex
)
2386 FOLDER_FILE_TYPE_ENTRY
*pEntry
= pEditType
->pEntry
;
2388 BOOL bIconSet
= FALSE
;
2389 if (IconPath
&& IconPath
[0])
2391 DestroyIcon(pEntry
->hIconLarge
);
2392 DestroyIcon(pEntry
->hIconSmall
);
2393 pEntry
->hIconLarge
= DoExtractIcon(pEntry
, IconPath
, IconIndex
, FALSE
);
2394 pEntry
->hIconSmall
= DoExtractIcon(pEntry
, IconPath
, IconIndex
, TRUE
);
2396 bIconSet
= (pEntry
->hIconLarge
&& pEntry
->hIconSmall
);
2400 StringCchCopyW(pEntry
->IconPath
, _countof(pEntry
->IconPath
), IconPath
);
2401 pEntry
->nIconIndex
= IconIndex
;
2405 SetFileTypeEntryDefaultIcon(pEntry
);
2408 HWND hListView
= pEditType
->hwndLV
;
2409 HIMAGELIST himlLarge
= ListView_GetImageList(hListView
, LVSIL_NORMAL
);
2410 HIMAGELIST himlSmall
= ListView_GetImageList(hListView
, LVSIL_SMALL
);
2412 INT iLargeImage
= ImageList_AddIcon(himlLarge
, pEntry
->hIconLarge
);
2413 INT iSmallImage
= ImageList_AddIcon(himlSmall
, pEntry
->hIconSmall
);
2414 ASSERT(iLargeImage
== iSmallImage
);
2416 INT iItem
= ListView_GetNextItem(hListView
, -1, LVNI_SELECTED
);
2419 LV_ITEMW Item
= { LVIF_IMAGE
, iItem
};
2420 Item
.iImage
= iSmallImage
;
2421 ListView_SetItem(hListView
, &Item
);
2427 EditTypeDlg_OnOK(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
)
2429 FOLDER_FILE_TYPE_ENTRY
*pEntry
= pEditType
->pEntry
;
2432 GetDlgItemTextW(hwndDlg
, IDC_EDITTYPE_TEXT
, pEntry
->ClassName
, _countof(pEntry
->ClassName
));
2433 StrTrimW(pEntry
->ClassName
, s_pszSpace
);
2435 // update entry icon
2436 EditTypeDlg_UpdateEntryIcon(hwndDlg
, pEditType
, pEditType
->szIconPath
, pEditType
->nIconIndex
);
2439 EditTypeDlg_WriteClass(hwndDlg
, pEditType
, pEntry
->ClassKey
, pEntry
->ClassName
, _countof(pEntry
->ClassName
));
2441 // update the icon cache
2442 SHChangeNotify(SHCNE_ASSOCCHANGED
, SHCNF_FLUSHNOWAIT
, NULL
, NULL
);
2444 EndDialog(hwndDlg
, IDOK
);
2447 struct ACTION_DIALOG
2450 WCHAR ClassName
[64];
2452 WCHAR szApp
[MAX_PATH
];
2457 NewAct_OnOK(HWND hwndDlg
, ACTION_DIALOG
*pNewAct
)
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)
2465 // action is empty, error
2466 HWND hwndCtrl
= GetDlgItem(hwndDlg
, IDC_ACTION_ACTION
);
2467 SendMessageW(hwndCtrl
, EM_SETSEL
, 0, -1);
2469 CStringW
strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION
));
2470 CStringW
strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES
));
2471 MessageBoxW(hwndDlg
, strText
, strTitle
, MB_ICONERROR
);
2474 if (pNewAct
->szApp
[0] == 0 || GetFileAttributesW(pNewAct
->szApp
) == 0xFFFFFFFF)
2477 HWND hwndCtrl
= GetDlgItem(hwndDlg
, IDC_ACTION_APP
);
2478 SendMessageW(hwndCtrl
, EM_SETSEL
, 0, -1);
2480 CStringW
strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM
));
2481 CStringW
strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES
));
2482 MessageBoxW(hwndDlg
, strText
, strTitle
, MB_ICONERROR
);
2485 EndDialog(hwndDlg
, IDOK
);
2489 Action_OnBrowse(HWND hwndDlg
, ACTION_DIALOG
*pNewAct
, BOOL bEdit
= FALSE
)
2491 WCHAR szFile
[MAX_PATH
];
2494 WCHAR szFilter
[MAX_PATH
];
2495 LoadStringW(shell32_hInstance
, IDS_EXE_FILTER
, szFilter
, _countof(szFilter
));
2497 CStringW
strTitle(MAKEINTRESOURCEW(IDS_OPEN_WITH
));
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
))
2513 CStringW str
= szFile
;
2515 SetDlgItemTextW(hwndDlg
, IDC_ACTION_APP
, str
);
2519 SetDlgItemTextW(hwndDlg
, IDC_ACTION_APP
, szFile
);
2525 NewActionDlgProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2527 static ACTION_DIALOG
*s_pNewAct
= NULL
;
2532 s_pNewAct
= (ACTION_DIALOG
*)lParam
;
2533 s_pNewAct
->bUseDDE
= FALSE
;
2534 EnableWindow(GetDlgItem(hwndDlg
, IDC_ACTION_USE_DDE
), FALSE
);
2538 switch (LOWORD(wParam
))
2541 NewAct_OnOK(hwndDlg
, s_pNewAct
);
2545 EndDialog(hwndDlg
, IDCANCEL
);
2548 case IDC_ACTION_BROWSE
:
2549 Action_OnBrowse(hwndDlg
, s_pNewAct
, FALSE
);
2558 EditAct_OnOK(HWND hwndDlg
, ACTION_DIALOG
*pEditAct
)
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)
2566 HWND hwndCtrl
= GetDlgItem(hwndDlg
, IDC_ACTION_ACTION
);
2567 SendMessageW(hwndCtrl
, EM_SETSEL
, 0, -1);
2569 CStringW
strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION
));
2570 CStringW
strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES
));
2571 MessageBoxW(hwndDlg
, strText
, strTitle
, MB_ICONERROR
);
2573 if (pEditAct
->szApp
[0] == 0)
2575 HWND hwndCtrl
= GetDlgItem(hwndDlg
, IDC_ACTION_APP
);
2576 SendMessageW(hwndCtrl
, EM_SETSEL
, 0, -1);
2578 CStringW
strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM
));
2579 CStringW
strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES
));
2580 MessageBoxW(hwndDlg
, strText
, strTitle
, MB_ICONERROR
);
2582 EndDialog(hwndDlg
, IDOK
);
2586 EditActionDlgProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2588 static ACTION_DIALOG
*s_pEditAct
= NULL
;
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
);
2601 CStringW
str(MAKEINTRESOURCEW(IDS_EDITING_ACTION
));
2602 str
+= s_pEditAct
->ClassName
;
2603 SetWindowTextW(hwndDlg
, str
);
2608 switch (LOWORD(wParam
))
2611 EditAct_OnOK(hwndDlg
, s_pEditAct
);
2615 EndDialog(hwndDlg
, IDCANCEL
);
2618 case IDC_ACTION_BROWSE
:
2619 Action_OnBrowse(hwndDlg
, s_pEditAct
, TRUE
);
2628 EditTypeDlg_OnChangeIcon(HWND hwndDlg
, EDITTYPE_DIALOG
*pEditType
)
2630 WCHAR szPath
[MAX_PATH
];
2633 ExpandEnvironmentStringsW(pEditType
->szIconPath
, szPath
, _countof(szPath
));
2634 IconIndex
= pEditType
->nIconIndex
;
2635 if (PickIconDlg(hwndDlg
, szPath
, _countof(szPath
), &IconIndex
))
2637 // replace Windows directory with "%SystemRoot%" (for portability)
2638 WCHAR szWinDir
[MAX_PATH
];
2639 GetWindowsDirectoryW(szWinDir
, _countof(szWinDir
));
2640 if (wcsstr(szPath
, szWinDir
) == 0)
2642 CStringW
str(L
"%SystemRoot%");
2643 str
+= &szPath
[wcslen(szWinDir
)];
2644 StringCchCopyW(szPath
, _countof(szPath
), LPCWSTR(str
));
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
);
2654 // update EDITTYPE_DIALOG
2655 StringCchCopyW(pEditType
->szIconPath
, _countof(pEditType
->szIconPath
), szPath
);
2656 pEditType
->nIconIndex
= IconIndex
;
2658 // set icon to dialog
2659 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_ICON
, STM_SETICON
, (WPARAM
)pEntry
->hIconLarge
, 0);
2664 EditTypeDlg_OnDrawItem(HWND hwndDlg
, LPDRAWITEMSTRUCT pDraw
, EDITTYPE_DIALOG
*pEditType
)
2667 HFONT hFont
, hFont2
;
2672 // fill rect and set colors
2673 if (pDraw
->itemState
& ODS_SELECTED
)
2675 FillRect(pDraw
->hDC
, &pDraw
->rcItem
, HBRUSH(COLOR_HIGHLIGHT
+ 1));
2676 SetTextColor(pDraw
->hDC
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
2677 SetBkColor(pDraw
->hDC
, GetSysColor(COLOR_HIGHLIGHT
));
2681 FillRect(pDraw
->hDC
, &pDraw
->rcItem
, HBRUSH(COLOR_WINDOW
+ 1));
2682 SetTextColor(pDraw
->hDC
, GetSysColor(COLOR_WINDOWTEXT
));
2683 SetBkColor(pDraw
->hDC
, GetSysColor(COLOR_WINDOW
));
2687 SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, LB_GETTEXT
, pDraw
->itemID
, (LPARAM
)szText
);
2690 hFont
= (HFONT
)SendDlgItemMessageW(hwndDlg
, IDC_EDITTYPE_LISTBOX
, WM_GETFONT
, 0, 0);
2691 if (lstrcmpiW(pEditType
->szDefaultVerb
, szText
) == 0)
2693 // default. set bold
2695 GetObject(hFont
, sizeof(lf
), &lf
);
2696 lf
.lfWeight
= FW_BOLD
;
2697 hFont2
= CreateFontIndirectW(&lf
);
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
);
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);
2717 if (pDraw
->itemState
& ODS_FOCUS
)
2719 DrawFocusRect(pDraw
->hDC
, &pDraw
->rcItem
);
2725 EditTypeDlg_OnMeasureItem(HWND hwndDlg
, LPMEASUREITEMSTRUCT pMeasure
, EDITTYPE_DIALOG
*pEditType
)
2730 HWND hwndLB
= GetDlgItem(hwndDlg
, IDC_EDITTYPE_LISTBOX
);
2733 GetClientRect(hwndLB
, &rc
);
2735 HDC hDC
= GetDC(hwndLB
);
2739 GetTextMetricsW(hDC
, &tm
);
2740 pMeasure
->itemWidth
= rc
.right
- rc
.left
;
2741 pMeasure
->itemHeight
= tm
.tmHeight
+ 4;
2742 ReleaseDC(hwndLB
, hDC
);
2749 EditTypeDlg_OnCommand(HWND hwndDlg
, UINT id
, UINT code
, EDITTYPE_DIALOG
*pEditType
)
2752 ACTION_DIALOG action
;
2756 EditTypeDlg_OnOK(hwndDlg
, pEditType
);
2760 EndDialog(hwndDlg
, IDCANCEL
);
2763 case IDC_EDITTYPE_CHANGE_ICON
:
2764 EditTypeDlg_OnChangeIcon(hwndDlg
, pEditType
);
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
)))
2775 if (SendMessageW(action
.hwndLB
, LB_FINDSTRING
, -1, (LPARAM
)action
.szAction
) != LB_ERR
)
2777 // already exists, error
2778 HWND hwndCtrl
= GetDlgItem(hwndDlg
, IDC_ACTION_ACTION
);
2779 SendMessageW(hwndCtrl
, EM_SETSEL
, 0, -1);
2782 CStringW strText
, strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES
));
2783 strText
.Format(IDS_ACTION_EXISTS
, action
.szAction
);
2784 MessageBoxW(hwndDlg
, strText
, strTitle
, MB_ICONERROR
);
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)
2796 StringCchCopyW(pEditType
->szDefaultVerb
, _countof(pEditType
->szDefaultVerb
), action
.szAction
);
2797 InvalidateRect(action
.hwndLB
, NULL
, TRUE
);
2803 case IDC_EDITTYPE_LISTBOX
:
2804 if (code
== LBN_SELCHANGE
)
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)
2811 EnableWindow(GetDlgItem(hwndDlg
, IDC_EDITTYPE_SET_DEFAULT
), FALSE
);
2815 EnableWindow(GetDlgItem(hwndDlg
, IDC_EDITTYPE_SET_DEFAULT
), TRUE
);
2819 else if (code
!= LBN_DBLCLK
)
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
)
2834 SendMessageW(action
.hwndLB
, LB_GETTEXT
, iItem
, LPARAM(action
.szAction
));
2838 iIndex
= pEditType
->CommandLineMap
.FindKey(action
.szAction
);
2839 CStringW str
= pEditType
->CommandLineMap
.GetValueAt(iIndex
);
2840 StringCchCopyW(action
.szApp
, _countof(action
.szApp
), LPCWSTR(str
));
2844 if (IDOK
== DialogBoxParamW(shell32_hInstance
, MAKEINTRESOURCEW(IDD_ACTION
), hwndDlg
,
2845 EditActionDlgProc
, LPARAM(&action
)))
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
);
2853 case IDC_EDITTYPE_REMOVE
:
2854 EditTypeDlg_OnRemove(hwndDlg
, pEditType
);
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
)
2863 SendMessageW(action
.hwndLB
, LB_GETTEXT
, iItem
, LPARAM(action
.szAction
));
2866 StringCchCopyW(pEditType
->szDefaultVerb
, _countof(pEditType
->szDefaultVerb
), action
.szAction
);
2867 EnableWindow(GetDlgItem(hwndDlg
, IDC_EDITTYPE_SET_DEFAULT
), FALSE
);
2868 InvalidateRect(action
.hwndLB
, NULL
, TRUE
);
2874 EditTypeDlgProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2876 static EDITTYPE_DIALOG
*s_pEditType
= NULL
;
2877 LPDRAWITEMSTRUCT pDraw
;
2878 LPMEASUREITEMSTRUCT pMeasure
;
2883 s_pEditType
= (EDITTYPE_DIALOG
*)lParam
;
2884 return EditTypeDlg_OnInitDialog(hwndDlg
, s_pEditType
);
2887 pDraw
= LPDRAWITEMSTRUCT(lParam
);
2888 return EditTypeDlg_OnDrawItem(hwndDlg
, pDraw
, s_pEditType
);
2890 case WM_MEASUREITEM
:
2891 pMeasure
= LPMEASUREITEMSTRUCT(lParam
);
2892 return EditTypeDlg_OnMeasureItem(hwndDlg
, pMeasure
, s_pEditType
);
2895 EditTypeDlg_OnCommand(hwndDlg
, LOWORD(wParam
), HIWORD(wParam
), s_pEditType
);
2903 EditTypeDlg_OnDelete(HWND hwndDlg
)
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
)
2909 FileTypesDlg_RemoveExt(hwndDlg
);
2913 // IDD_FOLDER_OPTIONS_FILETYPES dialog
2916 FolderOptionsFileTypesDlg(
2923 PFOLDER_FILE_TYPE_ENTRY pItem
;
2925 NEWEXT_DIALOG newext
;
2926 EDITTYPE_DIALOG edittype
;
2931 pItem
= InitializeFileTypesListCtrl(hwndDlg
);
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
);
2940 switch(LOWORD(wParam
))
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
))
2947 FileTypesDlg_AddExt(hwndDlg
, newext
.szExt
, newext
.szFileType
);
2951 case IDC_FILETYPES_DELETE
:
2952 EditTypeDlg_OnDelete(hwndDlg
);
2955 case IDC_FILETYPES_CHANGE
:
2956 pItem
= GetListViewEntry(GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
));
2959 Info
.oaifInFlags
= OAIF_ALLOW_REGISTRATION
| OAIF_REGISTER_EXT
;
2960 Info
.pcszClass
= pItem
->FileExtension
;
2961 SHOpenWithDialog(hwndDlg
, &Info
);
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
);
2975 lppl
= (LPNMLISTVIEW
) lParam
;
2976 switch (lppl
->hdr
.code
)
2980 LV_KEYDOWN
*pKeyDown
= (LV_KEYDOWN
*)lParam
;
2981 if (pKeyDown
->wVKey
== VK_DELETE
)
2983 EditTypeDlg_OnDelete(hwndDlg
);
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
);
2995 case LVN_DELETEALLITEMS
:
2996 return FALSE
; // send LVN_DELETEITEM
2998 case LVN_DELETEITEM
:
2999 pItem
= GetListViewEntry(lppl
->hdr
.hwndFrom
, lppl
->iItem
);
3002 DestroyIcon(pItem
->hIconLarge
);
3003 DestroyIcon(pItem
->hIconSmall
);
3004 HeapFree(GetProcessHeap(), 0, pItem
);
3008 case LVN_ITEMCHANGING
:
3009 pItem
= GetListViewEntry(lppl
->hdr
.hwndFrom
, lppl
->iItem
);
3015 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
3017 FileTypesDlg_OnItemChanging(hwndDlg
, pItem
);
3022 /* On page activation, set the focus to the listview */
3023 SetFocus(GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
));
3034 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
3036 PROPSHEETHEADERW pinfo
;
3037 HPROPSHEETPAGE hppages
[3];
3038 HPROPSHEETPAGE hpage
;
3040 WCHAR szOptions
[100];
3042 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL
, FolderOptionsGeneralDlg
, 0, NULL
);
3044 hppages
[num_pages
++] = hpage
;
3046 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW
, FolderOptionsViewDlg
, 0, NULL
);
3048 hppages
[num_pages
++] = hpage
;
3050 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES
, FolderOptionsFileTypesDlg
, 0, NULL
);
3052 hppages
[num_pages
++] = hpage
;
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';
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
;
3065 PropertySheetW(&pinfo
);
3070 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
3075 ShowFolderOptionsDialog(hWnd
, hInst
);
3079 // show taskbar options dialog
3080 FIXME("notify explorer to show taskbar options dialog");
3081 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
3085 FIXME("unrecognized options id %d\n", fOptions
);
3089 /*************************************************************************
3090 * Options_RunDLL (SHELL32.@)
3092 EXTERN_C VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
3094 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
3097 /*************************************************************************
3098 * Options_RunDLLA (SHELL32.@)
3100 EXTERN_C VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
3102 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
3105 /*************************************************************************
3106 * Options_RunDLLW (SHELL32.@)
3108 EXTERN_C VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
3110 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);