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
];
40 } FOLDER_FILE_TYPE_ENTRY
, *PFOLDER_FILE_TYPE_ENTRY
;
42 // uniquely-defined icon entry for Advanced Settings
43 typedef struct ADVANCED_ICON
45 WCHAR szPath
[MAX_PATH
];
49 // predefined icon IDs (See CreateTreeImageList function below)
52 #define I_CHECKED_DISABLED 2
53 #define I_UNCHECKED_DISABLED 3
54 #define I_RADIO_CHECKED 4
55 #define I_RADIO_UNCHECKED 5
56 #define I_RADIO_CHECKED_DISABLED 6
57 #define I_RADIO_UNCHECKED_DISABLED 7
59 #define PREDEFINED_ICON_COUNT 8
61 // definition of icon stock
62 static ADVANCED_ICON
* s_AdvancedIcons
= NULL
;
63 static INT s_AdvancedIconCount
= 0;
64 static HIMAGELIST s_hImageList
= NULL
;
67 Advanced_FindIcon(LPCWSTR pszPath
, UINT nIconIndex
)
69 for (INT i
= PREDEFINED_ICON_COUNT
; i
< s_AdvancedIconCount
; ++i
)
71 ADVANCED_ICON
*pIcon
= &s_AdvancedIcons
[i
];
72 if (pIcon
->nIconIndex
== nIconIndex
&&
73 lstrcmpiW(pIcon
->szPath
, pszPath
) == 0)
78 return -1; // not found
82 Advanced_AddIcon(LPCWSTR pszPath
, UINT nIconIndex
)
84 ADVANCED_ICON
*pAllocated
;
86 // return the ID if already existed
87 INT nIconID
= Advanced_FindIcon(pszPath
, nIconIndex
);
89 return nIconID
; // already exists
91 // extract a small icon
92 HICON hIconSmall
= NULL
;
93 ExtractIconExW(pszPath
, nIconIndex
, NULL
, &hIconSmall
, 1);
94 if (hIconSmall
== NULL
)
97 // resize s_AdvancedIcons
98 size_t Size
= (s_AdvancedIconCount
+ 1) * sizeof(ADVANCED_ICON
);
99 pAllocated
= (ADVANCED_ICON
*)realloc(s_AdvancedIcons
, Size
);
100 if (pAllocated
== NULL
)
101 return -1; // failure
103 s_AdvancedIcons
= pAllocated
;
105 // save icon information
106 ADVANCED_ICON
*pIcon
= &s_AdvancedIcons
[s_AdvancedIconCount
];
107 lstrcpynW(pIcon
->szPath
, pszPath
, _countof(pIcon
->szPath
));
108 pIcon
->nIconIndex
= nIconIndex
;
110 // add the icon to the image list
111 ImageList_AddIcon(s_hImageList
, hIconSmall
);
113 // increment the counter
114 nIconID
= s_AdvancedIconCount
;
115 ++s_AdvancedIconCount
;
117 DestroyIcon(hIconSmall
);
119 return nIconID
; // newly-added icon ID
122 // types of Advanced Setting entry
123 typedef enum ADVANCED_ENTRY_TYPE
128 } ADVANCED_ENTRY_TYPE
;
130 // an entry info of Advanced Settings
131 typedef struct ADVANCED_ENTRY
133 DWORD dwID
; // entry ID
134 DWORD dwParentID
; // parent entry ID
135 DWORD dwResourceID
; // resource ID
136 WCHAR szKeyName
[64]; // entry key name
137 DWORD dwType
; // ADVANCED_ENTRY_TYPE
138 WCHAR szText
[MAX_PATH
]; // text
139 INT nIconID
; // icon ID (See ADVANCED_ICON)
141 HKEY hkeyRoot
; // registry root key
142 WCHAR szRegPath
[MAX_PATH
]; // registry path
143 WCHAR szValueName
[64]; // registry value name
145 DWORD dwCheckedValue
; // checked value
146 DWORD dwUncheckedValue
; // unchecked value
147 DWORD dwDefaultValue
; // defalut value
148 BOOL bHasUncheckedValue
; // If FALSE, UncheckedValue is invalid
150 HTREEITEM hItem
; // for TreeView
151 BOOL bGrayed
; // disabled?
152 BOOL bChecked
; // checked?
153 } ADVANCED_ENTRY
, *PADVANCED_ENTRY
;
155 // definition of advanced entries
156 static ADVANCED_ENTRY
* s_Advanced
= NULL
;
157 static INT s_AdvancedCount
= 0;
160 Create24BppBitmap(HDC hDC
, INT cx
, INT cy
)
165 ZeroMemory(&bi
, sizeof(bi
));
166 bi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
167 bi
.bmiHeader
.biWidth
= cx
;
168 bi
.bmiHeader
.biHeight
= cy
;
169 bi
.bmiHeader
.biPlanes
= 1;
170 bi
.bmiHeader
.biBitCount
= 24;
171 bi
.bmiHeader
.biCompression
= BI_RGB
;
173 HBITMAP hbm
= CreateDIBSection(hDC
, &bi
, DIB_RGB_COLORS
, &pvBits
, NULL
, 0);
178 CreateCheckImage(HDC hDC
, BOOL bCheck
, BOOL bEnabled
= TRUE
)
180 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
181 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
183 HBITMAP hbm
= Create24BppBitmap(hDC
, cxSmallIcon
, cySmallIcon
);
185 return NULL
; // failure
188 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
190 InflateRect(&BoxRect
, -1, -1);
192 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
194 UINT uState
= DFCS_BUTTONCHECK
| DFCS_FLAT
| DFCS_MONO
;
196 uState
|= DFCS_CHECKED
;
198 uState
|= DFCS_INACTIVE
;
199 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
201 SelectObject(hDC
, hbmOld
);
203 return hbm
; // success
207 CreateCheckMask(HDC hDC
)
209 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
210 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
212 HBITMAP hbm
= CreateBitmap(cxSmallIcon
, cySmallIcon
, 1, 1, NULL
);
214 return NULL
; // failure
217 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
219 InflateRect(&BoxRect
, -1, -1);
221 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
223 FillRect(hDC
, &Rect
, HBRUSH(GetStockObject(WHITE_BRUSH
)));
224 FillRect(hDC
, &BoxRect
, HBRUSH(GetStockObject(BLACK_BRUSH
)));
226 SelectObject(hDC
, hbmOld
);
228 return hbm
; // success
232 CreateRadioImage(HDC hDC
, BOOL bCheck
, BOOL bEnabled
= TRUE
)
234 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
235 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
237 HBITMAP hbm
= Create24BppBitmap(hDC
, cxSmallIcon
, cySmallIcon
);
239 return NULL
; // failure
242 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
244 InflateRect(&BoxRect
, -1, -1);
246 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
248 UINT uState
= DFCS_BUTTONRADIOIMAGE
| DFCS_FLAT
| DFCS_MONO
;
250 uState
|= DFCS_CHECKED
;
252 uState
|= DFCS_INACTIVE
;
253 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
255 SelectObject(hDC
, hbmOld
);
257 return hbm
; // success
261 CreateRadioMask(HDC hDC
)
263 INT cxSmallIcon
= GetSystemMetrics(SM_CXSMICON
);
264 INT cySmallIcon
= GetSystemMetrics(SM_CYSMICON
);
266 HBITMAP hbm
= CreateBitmap(cxSmallIcon
, cySmallIcon
, 1, 1, NULL
);
268 return NULL
; // failure
271 SetRect(&Rect
, 0, 0, cxSmallIcon
, cySmallIcon
);
273 InflateRect(&BoxRect
, -1, -1);
275 HGDIOBJ hbmOld
= SelectObject(hDC
, hbm
);
277 FillRect(hDC
, &Rect
, HBRUSH(GetStockObject(WHITE_BRUSH
)));
278 UINT uState
= DFCS_BUTTONRADIOMASK
| DFCS_FLAT
| DFCS_MONO
;
279 DrawFrameControl(hDC
, &BoxRect
, DFC_BUTTON
, uState
);
281 SelectObject(hDC
, hbmOld
);
283 return hbm
; // success
287 CreateTreeImageList(VOID
)
289 HIMAGELIST hImageList
;
290 hImageList
= ImageList_Create(16, 16, ILC_COLOR24
| ILC_MASK
, 9, 1);
291 if (hImageList
== NULL
)
292 return NULL
; // failure
297 free(s_AdvancedIcons
);
298 s_AdvancedIcons
= NULL
;
300 s_AdvancedIconCount
= 0;
303 ADVANCED_ICON
*pAllocated
;
304 size_t Size
= PREDEFINED_ICON_COUNT
* sizeof(ADVANCED_ICON
);
305 pAllocated
= (ADVANCED_ICON
*)calloc(1, Size
);
306 if (pAllocated
== NULL
)
307 return NULL
; // failure
309 s_AdvancedIconCount
= PREDEFINED_ICON_COUNT
;
310 s_AdvancedIcons
= pAllocated
;
312 // add the predefined icons
314 HDC hDC
= CreateCompatibleDC(NULL
);
315 HBITMAP hbmMask
= CreateCheckMask(hDC
);
317 HBITMAP hbmChecked
, hbmUnchecked
;
319 hbmChecked
= CreateCheckImage(hDC
, TRUE
);
320 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
321 DeleteObject(hbmChecked
);
323 hbmUnchecked
= CreateCheckImage(hDC
, FALSE
);
324 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
325 DeleteObject(hbmUnchecked
);
327 hbmChecked
= CreateCheckImage(hDC
, TRUE
, FALSE
);
328 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
329 DeleteObject(hbmChecked
);
331 hbmUnchecked
= CreateCheckImage(hDC
, FALSE
, FALSE
);
332 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
333 DeleteObject(hbmUnchecked
);
335 DeleteObject(hbmMask
);
336 hbmMask
= CreateRadioMask(hDC
);
338 hbmChecked
= CreateRadioImage(hDC
, TRUE
);
339 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
340 DeleteObject(hbmChecked
);
342 hbmUnchecked
= CreateRadioImage(hDC
, FALSE
);
343 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
344 DeleteObject(hbmUnchecked
);
346 hbmChecked
= CreateRadioImage(hDC
, TRUE
, FALSE
);
347 ImageList_Add(hImageList
, hbmChecked
, hbmMask
);
348 DeleteObject(hbmChecked
);
350 hbmUnchecked
= CreateRadioImage(hDC
, FALSE
, FALSE
);
351 ImageList_Add(hImageList
, hbmUnchecked
, hbmMask
);
352 DeleteObject(hbmUnchecked
);
354 DeleteObject(hbmMask
);
359 static ADVANCED_ENTRY
*
360 Advanced_GetItem(DWORD dwID
)
362 if (dwID
== DWORD(-1))
365 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
367 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
368 if (pEntry
->dwID
== dwID
)
371 return NULL
; // failure
375 Advanced_GetImage(ADVANCED_ENTRY
*pEntry
)
377 switch (pEntry
->dwType
)
380 return pEntry
->nIconID
;
382 case AETYPE_CHECKBOX
:
385 if (pEntry
->bChecked
)
386 return I_CHECKED_DISABLED
;
388 return I_UNCHECKED_DISABLED
;
392 if (pEntry
->bChecked
)
401 if (pEntry
->bChecked
)
402 return I_RADIO_CHECKED_DISABLED
;
404 return I_RADIO_UNCHECKED_DISABLED
;
408 if (pEntry
->bChecked
)
409 return I_RADIO_CHECKED
;
411 return I_RADIO_UNCHECKED
;
414 return -1; // failure
418 Advanced_InsertEntry(HWND hwndTreeView
, ADVANCED_ENTRY
*pEntry
)
420 ADVANCED_ENTRY
*pParent
= Advanced_GetItem(pEntry
->dwParentID
);
421 HTREEITEM hParent
= TVI_ROOT
;
423 hParent
= pParent
->hItem
;
425 TV_INSERTSTRUCT Insertion
;
426 ZeroMemory(&Insertion
, sizeof(Insertion
));
427 Insertion
.hParent
= hParent
;
428 Insertion
.hInsertAfter
= TVI_LAST
;
429 Insertion
.item
.mask
=
430 TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
431 Insertion
.item
.pszText
= pEntry
->szText
;
433 INT iImage
= Advanced_GetImage(pEntry
);
434 Insertion
.item
.iImage
= Insertion
.item
.iSelectedImage
= iImage
;
435 Insertion
.item
.lParam
= pEntry
->dwID
;
436 pEntry
->hItem
= TreeView_InsertItem(hwndTreeView
, &Insertion
);
440 Advanced_InsertAll(HWND hwndTreeView
)
442 TreeView_DeleteAllItems(hwndTreeView
);
444 // insert the entries
445 ADVANCED_ENTRY
*pEntry
;
446 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
448 pEntry
= &s_Advanced
[i
];
449 Advanced_InsertEntry(hwndTreeView
, pEntry
);
453 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
455 pEntry
= &s_Advanced
[i
];
456 if (pEntry
->dwType
== AETYPE_GROUP
)
458 TreeView_Expand(hwndTreeView
, pEntry
->hItem
, TVE_EXPAND
);
464 Advanced_LoadTree(HKEY hKey
, LPCWSTR pszKeyName
, DWORD dwParentID
)
467 WCHAR szKeyName
[64], szText
[MAX_PATH
], *pch
;
469 ADVANCED_ENTRY
*pAllocated
;
472 Size
= (s_AdvancedCount
+ 1) * sizeof(ADVANCED_ENTRY
);
473 pAllocated
= (ADVANCED_ENTRY
*)realloc(s_Advanced
, Size
);
474 if (pAllocated
== NULL
)
475 return FALSE
; // failure
477 s_Advanced
= pAllocated
;
479 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[s_AdvancedCount
];
481 // dwID, dwParentID, szKeyName
482 pEntry
->dwID
= s_AdvancedCount
;
483 pEntry
->dwParentID
= dwParentID
;
484 lstrcpynW(pEntry
->szKeyName
, pszKeyName
, _countof(pEntry
->szKeyName
));
487 pEntry
->szText
[0] = 0;
488 pEntry
->dwResourceID
= 0;
490 Size
= sizeof(szText
);
491 RegQueryValueExW(hKey
, L
"Text", NULL
, NULL
, LPBYTE(szText
), &Size
);
492 if (szText
[0] == L
'@')
494 pch
= wcsrchr(szText
, L
',');
498 dwIndex
= abs(_wtoi(pch
+ 1));
499 pEntry
->dwResourceID
= dwIndex
;
501 HINSTANCE hInst
= LoadLibraryW(&szText
[1]);
502 LoadStringW(hInst
, dwIndex
, szText
, _countof(szText
));
507 pEntry
->dwResourceID
= DWORD(-1);
509 lstrcpynW(pEntry
->szText
, szText
, _countof(pEntry
->szText
));
513 RegQueryValueExW(hKey
, L
"Type", NULL
, NULL
, LPBYTE(szText
), &Size
);
514 if (lstrcmpiW(szText
, L
"checkbox") == 0)
515 pEntry
->dwType
= AETYPE_CHECKBOX
;
516 else if (lstrcmpiW(szText
, L
"radio") == 0)
517 pEntry
->dwType
= AETYPE_RADIO
;
518 else if (lstrcmpiW(szText
, L
"group") == 0)
519 pEntry
->dwType
= AETYPE_GROUP
;
521 return FALSE
; // failure
523 pEntry
->nIconID
= -1;
524 if (pEntry
->dwType
== AETYPE_GROUP
)
528 Size
= sizeof(szText
);
530 RegQueryValueExW(hKey
, L
"Bitmap", NULL
, NULL
, LPBYTE(szText
), &Size
);
532 WCHAR szExpanded
[MAX_PATH
];
533 ExpandEnvironmentStringsW(szText
, szExpanded
, _countof(szExpanded
));
534 pch
= wcsrchr(szExpanded
, L
',');
538 nIconIndex
= abs(_wtoi(pch
+ 1));
540 pEntry
->nIconID
= Advanced_AddIcon(szExpanded
, nIconIndex
);
543 if (pEntry
->dwType
== AETYPE_GROUP
)
545 pEntry
->hkeyRoot
= NULL
;
546 pEntry
->szRegPath
[0] = 0;
547 pEntry
->szValueName
[0] = 0;
548 pEntry
->dwCheckedValue
= 0;
549 pEntry
->bHasUncheckedValue
= FALSE
;
550 pEntry
->dwUncheckedValue
= 0;
551 pEntry
->dwDefaultValue
= 0;
552 pEntry
->hItem
= NULL
;
553 pEntry
->bGrayed
= FALSE
;
554 pEntry
->bChecked
= FALSE
;
559 Value
= DWORD(HKEY_CURRENT_USER
);
560 Size
= sizeof(Value
);
561 RegQueryValueExW(hKey
, L
"HKeyRoot", NULL
, NULL
, LPBYTE(&Value
), &Size
);
562 pEntry
->hkeyRoot
= HKEY(Value
);
565 pEntry
->szRegPath
[0] = 0;
566 Size
= sizeof(szText
);
567 RegQueryValueExW(hKey
, L
"RegPath", NULL
, NULL
, LPBYTE(szText
), &Size
);
568 lstrcpynW(pEntry
->szRegPath
, szText
, _countof(pEntry
->szRegPath
));
571 pEntry
->szValueName
[0] = 0;
572 Size
= sizeof(szText
);
573 RegQueryValueExW(hKey
, L
"ValueName", NULL
, NULL
, LPBYTE(szText
), &Size
);
574 lstrcpynW(pEntry
->szValueName
, szText
, _countof(pEntry
->szValueName
));
577 Size
= sizeof(Value
);
579 RegQueryValueExW(hKey
, L
"CheckedValue", NULL
, NULL
, LPBYTE(&Value
), &Size
);
580 pEntry
->dwCheckedValue
= Value
;
583 Size
= sizeof(Value
);
585 pEntry
->bHasUncheckedValue
= TRUE
;
586 if (RegQueryValueExW(hKey
, L
"UncheckedValue", NULL
,
587 NULL
, LPBYTE(&Value
), &Size
) != ERROR_SUCCESS
)
589 pEntry
->bHasUncheckedValue
= FALSE
;
591 pEntry
->dwUncheckedValue
= Value
;
594 Size
= sizeof(Value
);
596 RegQueryValueExW(hKey
, L
"DefaultValue", NULL
, NULL
, LPBYTE(&Value
), &Size
);
597 pEntry
->dwDefaultValue
= Value
;
600 pEntry
->hItem
= NULL
;
604 Value
= pEntry
->dwDefaultValue
;
605 pEntry
->bGrayed
= TRUE
;
606 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
, 0,
607 KEY_READ
, &hkeyTarget
) == ERROR_SUCCESS
)
609 Size
= sizeof(Value
);
610 if (RegQueryValueExW(hkeyTarget
, pEntry
->szValueName
, NULL
, NULL
,
611 LPBYTE(&Value
), &Size
) == ERROR_SUCCESS
)
613 pEntry
->bGrayed
= FALSE
;
615 RegCloseKey(hkeyTarget
);
617 pEntry
->bChecked
= (Value
== pEntry
->dwCheckedValue
);
620 // Grayed (ReactOS extension)
621 Size
= sizeof(Value
);
623 RegQueryValueExW(hKey
, L
"Grayed", NULL
, NULL
, LPBYTE(&Value
), &Size
);
624 if (!pEntry
->bGrayed
)
625 pEntry
->bGrayed
= Value
;
627 BOOL bIsGroup
= (pEntry
->dwType
== AETYPE_GROUP
);
628 dwParentID
= pEntry
->dwID
;
632 return TRUE
; // success
636 while (RegEnumKeyW(hKey
, dwIndex
, szKeyName
,
637 _countof(szKeyName
)) == ERROR_SUCCESS
)
640 if (RegOpenKeyExW(hKey
, szKeyName
, 0, KEY_READ
,
641 &hkeyChild
) != ERROR_SUCCESS
)
647 Advanced_LoadTree(hkeyChild
, szKeyName
, dwParentID
);
648 RegCloseKey(hkeyChild
);
653 return TRUE
; // success
657 Advanced_LoadAll(VOID
)
659 static const WCHAR s_szAdvanced
[] =
660 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
662 // free if already existed
671 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, s_szAdvanced
, 0,
672 KEY_READ
, &hKey
) != ERROR_SUCCESS
)
674 return FALSE
; // failure
680 while (RegEnumKeyW(hKey
, dwIndex
, szKeyName
,
681 _countof(szKeyName
)) == ERROR_SUCCESS
)
684 if (RegOpenKeyExW(hKey
, szKeyName
, 0, KEY_READ
,
685 &hkeyChild
) != ERROR_SUCCESS
)
691 Advanced_LoadTree(hkeyChild
, szKeyName
, DWORD(-1));
692 RegCloseKey(hkeyChild
);
699 return TRUE
; // success
703 Advanced_Compare(const void *x
, const void *y
)
705 ADVANCED_ENTRY
*pEntry1
= (ADVANCED_ENTRY
*)x
;
706 ADVANCED_ENTRY
*pEntry2
= (ADVANCED_ENTRY
*)y
;
708 DWORD dwParentID1
= pEntry1
->dwParentID
;
709 DWORD dwParentID2
= pEntry2
->dwParentID
;
711 if (dwParentID1
== dwParentID2
)
712 return lstrcmpi(pEntry1
->szText
, pEntry2
->szText
);
715 const UINT MAX_DEPTH
= 32;
716 ADVANCED_ENTRY
*pArray1
[MAX_DEPTH
];
717 ADVANCED_ENTRY
*pArray2
[MAX_DEPTH
];
719 // Make ancestor lists
720 for (i
= m
= n
= 0; i
< MAX_DEPTH
; ++i
)
722 ADVANCED_ENTRY
*pParent1
= Advanced_GetItem(dwParentID1
);
723 ADVANCED_ENTRY
*pParent2
= Advanced_GetItem(dwParentID2
);
724 if (!pParent1
&& !pParent2
)
729 pArray1
[m
++] = pParent1
;
730 dwParentID1
= pParent1
->dwParentID
;
734 pArray2
[n
++] = pParent2
;
735 dwParentID2
= pParent2
->dwParentID
;
740 for (i
= 0; i
< k
; ++i
)
742 INT nCompare
= lstrcmpi(pArray1
[m
- i
- 1]->szText
, pArray2
[n
- i
- 1]->szText
);
753 return lstrcmpi(pEntry1
->szText
, pEntry2
->szText
);
757 Advanced_SortAll(VOID
)
759 qsort(s_Advanced
, s_AdvancedCount
, sizeof(ADVANCED_ENTRY
), Advanced_Compare
);
762 EXTERN_C HPSXA WINAPI
SHCreatePropSheetExtArrayEx(HKEY hKey
, LPCWSTR pszSubKey
, UINT max_iface
, IDataObject
*pDataObj
);
765 UpdateGeneralIcons(HWND hDlg
)
767 HWND hwndTaskIcon
, hwndFolderIcon
, hwndClickIcon
;
768 HICON hTaskIcon
= NULL
, hFolderIcon
= NULL
, hClickIcon
= NULL
;
769 LPTSTR lpTaskIconName
= NULL
, lpFolderIconName
= NULL
, lpClickIconName
= NULL
;
771 // show task setting icon
772 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_COMMONTASKS
) == BST_CHECKED
)
773 lpTaskIconName
= MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS
);
774 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_CLASSICFOLDERS
) == BST_CHECKED
)
775 lpTaskIconName
= MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS
);
779 hTaskIcon
= (HICON
)LoadImage(shell32_hInstance
,
787 hwndTaskIcon
= GetDlgItem(hDlg
,
788 IDC_FOLDER_OPTIONS_TASKICON
);
791 SendMessage(hwndTaskIcon
,
799 // show Folder setting icons
800 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_SAMEWINDOW
) == BST_CHECKED
)
801 lpFolderIconName
= MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW
);
802 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_OWNWINDOW
) == BST_CHECKED
)
803 lpFolderIconName
= MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW
);
805 if (lpFolderIconName
)
807 hFolderIcon
= (HICON
)LoadImage(shell32_hInstance
,
815 hwndFolderIcon
= GetDlgItem(hDlg
,
816 IDC_FOLDER_OPTIONS_FOLDERICON
);
819 SendMessage(hwndFolderIcon
,
822 (LPARAM
)hFolderIcon
);
827 // Show click setting icon
828 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_SINGLECLICK
) == BST_CHECKED
)
829 lpClickIconName
= MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN
);
830 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_DOUBLECLICK
) == BST_CHECKED
)
831 lpClickIconName
= MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN
);
835 hClickIcon
= (HICON
)LoadImage(shell32_hInstance
,
843 hwndClickIcon
= GetDlgItem(hDlg
,
844 IDC_FOLDER_OPTIONS_CLICKICON
);
847 SendMessage(hwndClickIcon
,
857 DeleteObject(hTaskIcon
);
859 DeleteObject(hFolderIcon
);
861 DeleteObject(hClickIcon
);
868 FolderOptionsGeneralDlg(
882 switch (LOWORD(wParam
))
884 case IDC_FOLDER_OPTIONS_COMMONTASKS
:
885 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS
:
886 case IDC_FOLDER_OPTIONS_SAMEWINDOW
:
887 case IDC_FOLDER_OPTIONS_OWNWINDOW
:
888 case IDC_FOLDER_OPTIONS_SINGLECLICK
:
889 case IDC_FOLDER_OPTIONS_DOUBLECLICK
:
890 if (HIWORD(wParam
) == BN_CLICKED
)
892 UpdateGeneralIcons(hwndDlg
);
894 /* Enable the 'Apply' button */
895 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
903 LPNMHDR pnmh
= (LPNMHDR
)lParam
;
926 ViewDlg_OnInitDialog(HWND hwndDlg
)
928 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
930 s_hImageList
= CreateTreeImageList();
931 TreeView_SetImageList(hwndTreeView
, s_hImageList
, TVSIL_NORMAL
);
935 Advanced_InsertAll(hwndTreeView
);
937 return TRUE
; // set focus
941 ViewDlg_ToggleCheckItem(HWND hwndDlg
, HTREEITEM hItem
)
943 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
948 ZeroMemory(&Item
, sizeof(Item
));
949 Item
.mask
= TVIF_HANDLE
| TVIF_IMAGE
| TVIF_PARAM
;
951 if (!TreeView_GetItem(hwndTreeView
, &Item
))
952 return FALSE
; // no such item
954 ADVANCED_ENTRY
*pEntry
= Advanced_GetItem(Item
.lParam
);
956 return FALSE
; // no such item
958 return FALSE
; // disabled
961 Item
.mask
= TVIF_HANDLE
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
962 switch (pEntry
->dwType
)
964 case AETYPE_CHECKBOX
:
965 pEntry
->bChecked
= !pEntry
->bChecked
;
968 // reset all the entries of the same parent
969 for (i
= 0; i
< s_AdvancedCount
; ++i
)
971 ADVANCED_ENTRY
*pEntry2
= &s_Advanced
[i
];
972 if (pEntry
->dwParentID
== pEntry2
->dwParentID
)
974 pEntry2
->bChecked
= FALSE
;
976 Item
.hItem
= pEntry2
->hItem
;
977 INT iImage
= Advanced_GetImage(pEntry2
);
978 Item
.iImage
= Item
.iSelectedImage
= iImage
;
979 TreeView_SetItem(hwndTreeView
, &Item
);
982 pEntry
->bChecked
= TRUE
;
985 return FALSE
; // failure
987 Item
.iImage
= Item
.iSelectedImage
= Advanced_GetImage(pEntry
);
989 TreeView_SetItem(hwndTreeView
, &Item
);
993 TreeView_GetItemRect(hwndTreeView
, hItem
, &rcItem
, FALSE
);
994 InvalidateRect(hwndTreeView
, &rcItem
, TRUE
);
995 return TRUE
; // success
999 ViewDlg_OnTreeViewClick(HWND hwndDlg
)
1001 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
1003 // do hit test to get the clicked item
1004 TV_HITTESTINFO HitTest
;
1005 ZeroMemory(&HitTest
, sizeof(HitTest
));
1006 DWORD dwPos
= GetMessagePos();
1007 HitTest
.pt
.x
= LOWORD(dwPos
);
1008 HitTest
.pt
.y
= HIWORD(dwPos
);
1009 ScreenToClient(hwndTreeView
, &HitTest
.pt
);
1010 HTREEITEM hItem
= TreeView_HitTest(hwndTreeView
, &HitTest
);
1012 // toggle the check mark if possible
1013 if (ViewDlg_ToggleCheckItem(hwndDlg
, hItem
))
1015 // property sheet was changed
1016 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1021 ViewDlg_OnTreeViewKeyDown(HWND hwndDlg
, TV_KEYDOWN
*KeyDown
)
1023 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
1025 if (KeyDown
->wVKey
== VK_SPACE
)
1027 // [Space] key was pressed
1028 HTREEITEM hItem
= TreeView_GetSelection(hwndTreeView
);
1029 if (ViewDlg_ToggleCheckItem(hwndDlg
, hItem
))
1031 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1037 ViewDlg_OnTreeCustomDraw(HWND hwndDlg
, NMTVCUSTOMDRAW
*Draw
)
1039 NMCUSTOMDRAW
& nmcd
= Draw
->nmcd
;
1040 switch (nmcd
.dwDrawStage
)
1043 return CDRF_NOTIFYITEMDRAW
; // for CDDS_ITEMPREPAINT
1045 case CDDS_ITEMPREPAINT
:
1046 if (!(nmcd
.uItemState
& CDIS_SELECTED
)) // not selected
1048 LPARAM lParam
= nmcd
.lItemlParam
;
1049 ADVANCED_ENTRY
*pEntry
= Advanced_GetItem(lParam
);
1050 if (pEntry
&& pEntry
->bGrayed
) // disabled
1053 Draw
->clrText
= GetSysColor(COLOR_GRAYTEXT
);
1054 Draw
->clrTextBk
= GetSysColor(COLOR_WINDOW
);
1055 return CDRF_NEWFONT
;
1063 return CDRF_DODEFAULT
;
1067 Advanced_RestoreDefaults(HWND hwndDlg
)
1069 HWND hwndTreeView
= GetDlgItem(hwndDlg
, 14003);
1071 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
1073 // ignore if the type is group
1074 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
1075 if (pEntry
->dwType
== AETYPE_GROUP
)
1078 // set default value on registry
1080 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
,
1081 0, KEY_WRITE
, &hKey
) != ERROR_SUCCESS
)
1085 RegSetValueExW(hKey
, pEntry
->szValueName
, 0, REG_DWORD
,
1086 LPBYTE(pEntry
->dwDefaultValue
), sizeof(DWORD
));
1089 // update check status
1090 pEntry
->bChecked
= (pEntry
->dwCheckedValue
== pEntry
->dwDefaultValue
);
1094 ZeroMemory(&Item
, sizeof(Item
));
1095 Item
.mask
= TVIF_HANDLE
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
1096 Item
.hItem
= pEntry
->hItem
;
1097 Item
.iImage
= Item
.iSelectedImage
= Advanced_GetImage(pEntry
);
1098 TreeView_SetItem(hwndTreeView
, &Item
);
1101 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
1104 /* FIXME: These macros should not be defined here */
1105 #ifndef SSF_SHOWSUPERHIDDEN
1106 #define SSF_SHOWSUPERHIDDEN 0x00040000
1108 #ifndef SSF_SEPPROCESS
1109 #define SSF_SEPPROCESS 0x00080000
1113 ScanAdvancedSettings(SHELLSTATE
*pSS
, DWORD
*pdwMask
)
1115 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
1117 const ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
1118 if (pEntry
->dwType
== AETYPE_GROUP
|| pEntry
->bGrayed
)
1121 BOOL bChecked
= pEntry
->bChecked
;
1123 // FIXME: Add more items
1124 if (lstrcmpiW(pEntry
->szKeyName
, L
"SuperHidden") == 0)
1126 pSS
->fShowSuperHidden
= !bChecked
? 1 : 0;
1127 *pdwMask
|= SSF_SHOWSUPERHIDDEN
;
1130 if (lstrcmpiW(pEntry
->szKeyName
, L
"DesktopProcess") == 0)
1132 pSS
->fSepProcess
= bChecked
? 1 : 0;
1133 *pdwMask
|= SSF_SEPPROCESS
;
1136 if (lstrcmpiW(pEntry
->szKeyName
, L
"SHOWALL") == 0)
1138 pSS
->fShowAllObjects
= !bChecked
? 1 : 0;
1139 *pdwMask
|= SSF_SHOWALLOBJECTS
;
1142 if (lstrcmpiW(pEntry
->szKeyName
, L
"HideFileExt") == 0)
1144 pSS
->fShowExtensions
= !bChecked
? 1 : 0;
1145 *pdwMask
|= SSF_SHOWEXTENSIONS
;
1148 if (lstrcmpiW(pEntry
->szKeyName
, L
"ShowCompColor") == 0)
1150 pSS
->fShowCompColor
= bChecked
? 1 : 0;
1151 *pdwMask
|= SSF_SHOWCOMPCOLOR
;
1154 if (lstrcmpiW(pEntry
->szKeyName
, L
"ShowInfoTip") == 0)
1156 pSS
->fShowInfoTip
= bChecked
? 1 : 0;
1157 *pdwMask
|= SSF_SHOWINFOTIP
;
1164 VOID WINAPI
SHGetSetSettings(LPSHELLSTATE lpss
, DWORD dwMask
, BOOL bSet
);
1166 static BOOL CALLBACK
RefreshBrowsersCallback (HWND hWnd
, LPARAM msg
)
1168 WCHAR ClassName
[100];
1169 if (GetClassName(hWnd
, ClassName
, 100))
1171 if (!wcscmp(ClassName
, L
"Progman") ||
1172 !wcscmp(ClassName
, L
"CabinetWClass") ||
1173 !wcscmp(ClassName
, L
"ExploreWClass"))
1175 PostMessage(hWnd
, WM_COMMAND
, FCIDM_DESKBROWSER_REFRESH
, 0);
1182 ViewDlg_Apply(HWND hwndDlg
)
1184 for (INT i
= 0; i
< s_AdvancedCount
; ++i
)
1186 // ignore the entry if the type is group or the entry is grayed
1187 ADVANCED_ENTRY
*pEntry
= &s_Advanced
[i
];
1188 if (pEntry
->dwType
== AETYPE_GROUP
|| pEntry
->bGrayed
)
1191 // open the registry key
1193 if (RegOpenKeyExW(HKEY(pEntry
->hkeyRoot
), pEntry
->szRegPath
, 0,
1194 KEY_WRITE
, &hkeyTarget
) != ERROR_SUCCESS
)
1199 // checked or unchecked?
1200 DWORD dwValue
, dwSize
;
1201 if (pEntry
->bChecked
)
1203 dwValue
= pEntry
->dwCheckedValue
;
1207 if (pEntry
->bHasUncheckedValue
)
1209 dwValue
= pEntry
->dwUncheckedValue
;
1213 // there is no unchecked value
1214 RegCloseKey(hkeyTarget
);
1220 dwSize
= sizeof(dwValue
);
1221 RegSetValueExW(hkeyTarget
, pEntry
->szValueName
, 0, REG_DWORD
,
1222 LPBYTE(&dwValue
), dwSize
);
1225 RegCloseKey(hkeyTarget
);
1228 // scan advanced settings for user's settings
1230 SHELLSTATE ShellState
;
1231 ZeroMemory(&ShellState
, sizeof(ShellState
));
1232 ScanAdvancedSettings(&ShellState
, &dwMask
);
1234 // update user's settings
1235 SHGetSetSettings(&ShellState
, dwMask
, TRUE
);
1238 SendMessage(HWND_BROADCAST
, WM_WININICHANGE
, 0, 0);
1240 EnumWindows(RefreshBrowsersCallback
, NULL
);
1244 FolderOptionsViewDlg(
1251 NMTVCUSTOMDRAW
*Draw
;
1256 return ViewDlg_OnInitDialog(hwndDlg
);
1258 switch (LOWORD(wParam
))
1260 case 14004: // Restore Defaults
1261 Advanced_RestoreDefaults(hwndDlg
);
1266 switch (LPNMHDR(lParam
)->code
)
1268 case NM_CLICK
: // clicked on treeview
1269 ViewDlg_OnTreeViewClick(hwndDlg
);
1271 case NM_CUSTOMDRAW
: // custom draw (for graying)
1272 Draw
= (NMTVCUSTOMDRAW
*)lParam
;
1273 Result
= ViewDlg_OnTreeCustomDraw(hwndDlg
, Draw
);
1274 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, Result
);
1276 case TVN_KEYDOWN
: // key is down
1277 ViewDlg_OnTreeViewKeyDown(hwndDlg
, (TV_KEYDOWN
*)lParam
);
1279 case PSN_APPLY
: // [Apply] is clicked
1280 ViewDlg_Apply(hwndDlg
);
1293 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
1299 int columnSize
= 140;
1302 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
1304 /* default to english */
1305 wcscpy(szName
, L
"Extensions");
1308 /* make sure its null terminated */
1309 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
1311 GetClientRect(hDlgCtrl
, &clientRect
);
1312 ZeroMemory(&col
, sizeof(LV_COLUMN
));
1313 columnSize
= 140; //FIXME
1315 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_FMT
;
1316 col
.fmt
= LVCFMT_FIXED_WIDTH
;
1317 col
.cx
= columnSize
| LVCFMT_LEFT
;
1318 col
.cchTextMax
= wcslen(szName
);
1319 col
.pszText
= szName
;
1320 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&col
);
1322 if (!LoadStringW(shell32_hInstance
, IDS_FILE_TYPES
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
1324 /* default to english */
1325 wcscpy(szName
, L
"File Types");
1326 ERR("Failed to load localized string!\n");
1330 col
.cx
= clientRect
.right
- clientRect
.left
- columnSize
;
1331 col
.cchTextMax
= wcslen(szName
);
1332 col
.pszText
= szName
;
1333 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&col
);
1335 /* set full select style */
1336 dwStyle
= (DWORD
) SendMessage(hDlgCtrl
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1337 dwStyle
= dwStyle
| LVS_EX_FULLROWSELECT
;
1338 SendMessage(hDlgCtrl
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, dwStyle
);
1342 FindItem(HWND hDlgCtrl
, WCHAR
* ItemName
)
1344 LVFINDINFOW findInfo
;
1345 ZeroMemory(&findInfo
, sizeof(LVFINDINFOW
));
1347 findInfo
.flags
= LVFI_STRING
;
1348 findInfo
.psz
= ItemName
;
1349 return ListView_FindItem(hDlgCtrl
, 0, &findInfo
);
1354 InsertFileType(HWND hDlgCtrl
, WCHAR
* szName
, PINT iItem
, WCHAR
* szFile
)
1356 PFOLDER_FILE_TYPE_ENTRY Entry
;
1362 if (szName
[0] != L
'.')
1364 /* FIXME handle URL protocol handlers */
1368 /* allocate file type entry */
1369 Entry
= (PFOLDER_FILE_TYPE_ENTRY
)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY
));
1375 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szName
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
1377 HeapFree(GetProcessHeap(), 0, Entry
);
1381 /* FIXME check for duplicates */
1383 /* query for the default key */
1384 dwSize
= sizeof(Entry
->ClassKey
);
1385 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->ClassKey
, &dwSize
) != ERROR_SUCCESS
)
1387 /* no link available */
1388 Entry
->ClassKey
[0] = 0;
1391 if (Entry
->ClassKey
[0])
1394 /* try open linked key */
1395 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, Entry
->ClassKey
, 0, KEY_READ
, &hTemp
) == ERROR_SUCCESS
)
1397 /* use linked key */
1403 /* read friendly type name */
1404 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", Entry
->FileDescription
, sizeof(Entry
->FileDescription
), NULL
, 0, NULL
) != ERROR_SUCCESS
)
1406 /* read file description */
1407 dwSize
= sizeof(Entry
->FileDescription
);
1408 Entry
->FileDescription
[0] = 0;
1410 /* read default key */
1411 RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->FileDescription
, &dwSize
);
1414 /* Read the EditFlags value */
1415 Entry
->EditFlags
= 0;
1416 if (!RegQueryValueExW(hKey
, L
"EditFlags", NULL
, &dwType
, NULL
, &dwSize
))
1418 if ((dwType
== REG_DWORD
|| dwType
== REG_BINARY
) && dwSize
== sizeof(DWORD
))
1419 RegQueryValueExW(hKey
, L
"EditFlags", NULL
, NULL
, (LPBYTE
)&Entry
->EditFlags
, &dwSize
);
1425 /* Do not add excluded entries */
1426 if (Entry
->EditFlags
& 0x00000001) //FTA_Exclude
1428 HeapFree(GetProcessHeap(), 0, Entry
);
1432 /* convert extension to upper case */
1433 wcscpy(Entry
->FileExtension
, szName
);
1434 _wcsupr(Entry
->FileExtension
);
1436 if (!Entry
->FileDescription
[0])
1438 /* construct default 'FileExtensionFile' by formatting the uppercase extension
1439 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
1441 StringCchPrintf(Entry
->FileDescription
, _countof(Entry
->FileDescription
), szFile
, &Entry
->FileExtension
[1]);
1444 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
1445 lvItem
.mask
= LVIF_TEXT
| LVIF_PARAM
;
1446 lvItem
.iSubItem
= 0;
1447 lvItem
.pszText
= &Entry
->FileExtension
[1];
1448 lvItem
.iItem
= *iItem
;
1449 lvItem
.lParam
= (LPARAM
)Entry
;
1450 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
);
1452 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
1453 lvItem
.mask
= LVIF_TEXT
;
1454 lvItem
.pszText
= Entry
->FileDescription
;
1455 lvItem
.iItem
= *iItem
;
1456 lvItem
.iSubItem
= 1;
1457 ListView_SetItem(hDlgCtrl
, &lvItem
);
1465 ListViewCompareProc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
1467 PFOLDER_FILE_TYPE_ENTRY Entry1
, Entry2
;
1470 Entry1
= (PFOLDER_FILE_TYPE_ENTRY
)lParam1
;
1471 Entry2
= (PFOLDER_FILE_TYPE_ENTRY
)lParam2
;
1473 x
= wcsicmp(Entry1
->FileExtension
, Entry2
->FileExtension
);
1477 return wcsicmp(Entry1
->FileDescription
, Entry2
->FileDescription
);
1481 PFOLDER_FILE_TYPE_ENTRY
1482 InitializeFileTypesListCtrl(HWND hwndDlg
)
1492 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
1493 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
1496 if (!LoadStringW(shell32_hInstance
, IDS_FILE_EXT_TYPE
, szFile
, _countof(szFile
)))
1498 /* default to english */
1499 wcscpy(szFile
, L
"%s File");
1501 szFile
[(_countof(szFile
)) - 1] = 0;
1503 dwName
= _countof(szName
);
1505 while (RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
1507 InsertFileType(hDlgCtrl
, szName
, &iItem
, szFile
);
1508 dwName
= _countof(szName
);
1511 /* Leave if the list is empty */
1516 ListView_SortItems(hDlgCtrl
, ListViewCompareProc
, NULL
);
1518 /* select first item */
1519 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
1520 lvItem
.mask
= LVIF_STATE
;
1521 lvItem
.stateMask
= (UINT
)-1;
1522 lvItem
.state
= LVIS_FOCUSED
| LVIS_SELECTED
;
1524 ListView_SetItem(hDlgCtrl
, &lvItem
);
1526 lvItem
.mask
= LVIF_PARAM
;
1527 ListView_GetItem(hDlgCtrl
, &lvItem
);
1529 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
1533 PFOLDER_FILE_TYPE_ENTRY
1540 Count
= ListView_GetItemCount(hDlgCtrl
);
1542 for (Index
= 0; Index
< Count
; Index
++)
1544 ZeroMemory(&lvItem
, sizeof(LVITEM
));
1545 lvItem
.mask
= LVIF_PARAM
| LVIF_STATE
;
1546 lvItem
.iItem
= Index
;
1547 lvItem
.stateMask
= (UINT
) - 1;
1549 if (ListView_GetItem(hDlgCtrl
, &lvItem
))
1551 if (lvItem
.state
& LVIS_SELECTED
)
1552 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
1559 struct NEWEXT_DIALOG
1567 WCHAR szFileType
[64];
1571 NewExtDlg_OnAdvanced(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1573 // If "Advanced" button was clicked, then we shrink or expand the dialog.
1577 GetWindowRect(hwndDlg
, &rc
);
1578 rc
.bottom
= rc
.top
+ (pNewExt
->rcDlg
.bottom
- pNewExt
->rcDlg
.top
);
1580 GetWindowRect(GetDlgItem(hwndDlg
, IDOK
), &rc1
);
1581 MapWindowPoints(NULL
, hwndDlg
, (POINT
*)&rc1
, 2);
1583 GetWindowRect(GetDlgItem(hwndDlg
, IDCANCEL
), &rc2
);
1584 MapWindowPoints(NULL
, hwndDlg
, (POINT
*)&rc2
, 2);
1586 if (pNewExt
->bAdvanced
)
1588 rc1
.top
+= pNewExt
->dy
;
1589 rc1
.bottom
+= pNewExt
->dy
;
1591 rc2
.top
+= pNewExt
->dy
;
1592 rc2
.bottom
+= pNewExt
->dy
;
1594 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_ASSOC
), SW_SHOWNOACTIVATE
);
1595 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), SW_SHOWNOACTIVATE
);
1597 LoadStringW(shell32_hInstance
, IDS_NEWEXT_ADVANCED_LEFT
, szText
, _countof(szText
));
1598 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_ADVANCED
, szText
);
1600 SetFocus(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
));
1604 rc1
.top
-= pNewExt
->dy
;
1605 rc1
.bottom
-= pNewExt
->dy
;
1607 rc2
.top
-= pNewExt
->dy
;
1608 rc2
.bottom
-= pNewExt
->dy
;
1610 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_ASSOC
), SW_HIDE
);
1611 ShowWindow(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), SW_HIDE
);
1613 LoadStringW(shell32_hInstance
, IDS_NEWEXT_ADVANCED_RIGHT
, szText
, _countof(szText
));
1614 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_ADVANCED
, szText
);
1616 rc
.bottom
-= pNewExt
->dy
;
1618 LoadStringW(shell32_hInstance
, IDS_NEWEXT_NEW
, szText
, _countof(szText
));
1619 SetDlgItemTextW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, szText
);
1622 HDWP hDWP
= BeginDeferWindowPos(3);
1625 hDWP
= DeferWindowPos(hDWP
, GetDlgItem(hwndDlg
, IDOK
), NULL
,
1626 rc1
.left
, rc1
.top
, rc1
.right
- rc1
.left
, rc1
.bottom
- rc1
.top
,
1627 SWP_NOACTIVATE
| SWP_NOZORDER
);
1629 hDWP
= DeferWindowPos(hDWP
, GetDlgItem(hwndDlg
, IDCANCEL
), NULL
,
1630 rc2
.left
, rc2
.top
, rc2
.right
- rc2
.left
, rc2
.bottom
- rc2
.top
,
1631 SWP_NOACTIVATE
| SWP_NOZORDER
);
1633 hDWP
= DeferWindowPos(hDWP
, hwndDlg
, NULL
,
1634 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
1635 SWP_NOACTIVATE
| SWP_NOZORDER
);
1638 EndDeferWindowPos(hDWP
);
1642 NewExtDlg_OnInitDialog(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1646 pNewExt
->hwndDlg
= hwndDlg
;
1647 pNewExt
->bAdvanced
= FALSE
;
1649 GetWindowRect(hwndDlg
, &pNewExt
->rcDlg
);
1652 GetWindowRect(GetDlgItem(hwndDlg
, IDC_NEWEXT_EDIT
), &rc1
);
1653 GetWindowRect(GetDlgItem(hwndDlg
, IDC_NEWEXT_COMBOBOX
), &rc2
);
1654 pNewExt
->dy
= rc2
.top
- rc1
.top
;
1656 LoadStringW(shell32_hInstance
, IDS_NEWEXT_NEW
, szText
, _countof(szText
));
1657 SendDlgItemMessageW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, CB_ADDSTRING
, 0, (LPARAM
)szText
);
1658 SendDlgItemMessageW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, CB_SETCURSEL
, 0, 0);
1660 SendDlgItemMessageW(hwndDlg
, IDC_NEWEXT_EDIT
, EM_SETLIMITTEXT
, _countof(pNewExt
->szExt
) - 1, 0);
1662 NewExtDlg_OnAdvanced(hwndDlg
, pNewExt
);
1668 StringTrimW(LPWSTR pszText
)
1670 LPWSTR pch
= pszText
;
1671 while (iswspace(*pch
))
1674 LPWSTR pchFirst
, pchLast
;
1675 pchFirst
= pchLast
= pch
;
1676 while (*pch
&& !iswspace(*pch
))
1682 INT_PTR cch
= pchLast
- pchFirst
;
1683 MoveMemory(pszText
, pchFirst
, cch
* sizeof(WCHAR
));
1688 NewExtDlg_OnOK(HWND hwndDlg
, NEWEXT_DIALOG
*pNewExt
)
1693 GetDlgItemTextW(hwndDlg
, IDC_NEWEXT_EDIT
, pNewExt
->szExt
, _countof(pNewExt
->szExt
));
1694 StringTrimW(pNewExt
->szExt
);
1695 CharUpperW(pNewExt
->szExt
);
1697 GetDlgItemTextW(hwndDlg
, IDC_NEWEXT_COMBOBOX
, pNewExt
->szFileType
, _countof(pNewExt
->szFileType
));
1698 StringTrimW(pNewExt
->szFileType
);
1700 if (pNewExt
->szExt
[0] == 0)
1702 WCHAR szText
[128], szTitle
[128];
1703 LoadStringW(shell32_hInstance
, IDS_NEWEXT_SPECIFY_EXT
, szText
, _countof(szText
));
1704 szText
[_countof(szText
) - 1] = 0;
1705 LoadStringW(shell32_hInstance
, IDS_FILE_TYPES
, szTitle
, _countof(szTitle
));
1706 szTitle
[_countof(szTitle
) - 1] = 0;
1707 MessageBoxW(hwndDlg
, szText
, szTitle
, MB_ICONERROR
);
1711 ZeroMemory(&find
, sizeof(find
));
1712 find
.flags
= LVFI_STRING
;
1713 if (pNewExt
->szExt
[0] == L
'.')
1715 find
.psz
= &pNewExt
->szExt
[1];
1719 find
.psz
= pNewExt
->szExt
;
1722 iItem
= ListView_FindItem(pNewExt
->hwndLV
, -1, &find
);
1726 WCHAR szText
[256], szFormat
[256], szTitle
[64], szFileType
[64];
1730 ZeroMemory(&item
, sizeof(item
));
1731 item
.mask
= LVIF_TEXT
;
1732 item
.pszText
= szFileType
;
1733 item
.cchTextMax
= _countof(szFileType
);
1736 ListView_GetItem(pNewExt
->hwndLV
, &item
);
1739 LoadStringW(shell32_hInstance
, IDS_NEWEXT_ALREADY_ASSOC
, szFormat
, _countof(szFormat
));
1740 szText
[_countof(szFormat
) - 1] = 0;
1741 StringCchPrintfW(szText
, _countof(szText
), szFormat
, find
.psz
, szFileType
, find
.psz
, szFileType
);
1744 LoadStringW(shell32_hInstance
, IDS_NEWEXT_EXT_IN_USE
, szTitle
, _countof(szTitle
));
1745 szTitle
[_countof(szTitle
) - 1] = 0;
1747 if (MessageBoxW(hwndDlg
, szText
, szTitle
, MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1753 ListView_DeleteItem(pNewExt
->hwndLV
, iItem
);
1756 EndDialog(hwndDlg
, IDOK
);
1760 // IDD_NEWEXTENSION dialog
1763 NewExtensionDlgProc(
1769 static NEWEXT_DIALOG
*s_pNewExt
= NULL
;
1774 s_pNewExt
= (NEWEXT_DIALOG
*)lParam
;
1775 NewExtDlg_OnInitDialog(hwndDlg
, s_pNewExt
);
1778 switch (LOWORD(wParam
))
1781 NewExtDlg_OnOK(hwndDlg
, s_pNewExt
);
1784 EndDialog(hwndDlg
, IDCANCEL
);
1786 case IDC_NEWEXT_ADVANCED
:
1787 s_pNewExt
->bAdvanced
= !s_pNewExt
->bAdvanced
;
1788 NewExtDlg_OnAdvanced(hwndDlg
, s_pNewExt
);
1797 FileTypesDlg_AddExt(HWND hwndDlg
, LPCWSTR pszExt
, LPCWSTR pszFileType
)
1801 WCHAR szKey
[13]; // max. "ft4294967295" + "\0"
1804 // Search the next "ft%06u" key name
1807 StringCchPrintfW(szKey
, _countof(szKey
), TEXT("ft%06u"), dwValue
);
1809 nResult
= RegOpenKeyEx(HKEY_CLASSES_ROOT
, szKey
, 0, KEY_READ
, &hKey
);
1810 if (nResult
!= ERROR_SUCCESS
)
1815 } while (dwValue
!= 0);
1822 // Create new "ft%06u" key
1823 nResult
= RegCreateKeyEx(HKEY_CLASSES_ROOT
, szKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
);
1824 if (ERROR_SUCCESS
!= nResult
)
1829 // Create the ".ext" key
1831 if (*pszExt
== L
'.')
1833 StringCchPrintfW(szExt
, _countof(szExt
), TEXT(".%s"), pszExt
);
1835 nResult
= RegCreateKeyEx(HKEY_CLASSES_ROOT
, szExt
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
);
1837 if (ERROR_SUCCESS
!= nResult
)
1840 // Set the default value of ".ext" to "ft%06u"
1841 DWORD dwSize
= (lstrlen(szKey
) + 1) * sizeof(WCHAR
);
1842 RegSetValueExW(hKey
, NULL
, 0, REG_SZ
, (BYTE
*)szKey
, dwSize
);
1846 // Make up the file type name
1847 WCHAR szFile
[100], szFileFormat
[100];
1848 LoadStringW(shell32_hInstance
, IDS_FILE_EXT_TYPE
, szFileFormat
, _countof(szFileFormat
));
1849 szFile
[_countof(szFileFormat
) - 1] = 0;
1850 StringCchPrintfW(szFile
, _countof(szFile
), szFileFormat
, &szExt
[1]);
1852 // Insert an item to listview
1853 HWND hListView
= GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
);
1854 INT iItem
= ListView_GetItemCount(hListView
);
1855 INT iItemCopy
= iItem
;
1856 InsertFileType(hListView
, szExt
, &iItemCopy
, szFile
);
1859 ZeroMemory(&item
, sizeof(item
));
1860 item
.mask
= LVIF_STATE
| LVIF_TEXT
;
1862 item
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
1863 item
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
1864 item
.pszText
= &szExt
[1];
1865 ListView_SetItem(hListView
, &item
);
1867 item
.pszText
= szFile
;
1869 ListView_SetItem(hListView
, &item
);
1871 ListView_EnsureVisible(hListView
, iItem
, FALSE
);
1876 // IDD_FOLDER_OPTIONS_FILETYPES dialog
1879 FolderOptionsFileTypesDlg(
1887 WCHAR Buffer
[255], FormatBuffer
[255];
1888 PFOLDER_FILE_TYPE_ENTRY pItem
;
1890 NEWEXT_DIALOG newext
;
1895 pItem
= InitializeFileTypesListCtrl(hwndDlg
);
1897 /* Disable the Delete button if the listview is empty or
1898 the selected item should not be deleted by the user */
1899 if (pItem
== NULL
|| (pItem
->EditFlags
& 0x00000010)) // FTA_NoRemove
1900 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILETYPES_DELETE
), FALSE
);
1904 switch(LOWORD(wParam
))
1906 case IDC_FILETYPES_NEW
:
1907 newext
.hwndLV
= GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
);
1908 if (IDOK
== DialogBoxParamW(shell32_hInstance
, MAKEINTRESOURCEW(IDD_NEWEXTENSION
),
1909 hwndDlg
, NewExtensionDlgProc
, (LPARAM
)&newext
))
1911 FileTypesDlg_AddExt(hwndDlg
, newext
.szExt
, newext
.szFileType
);
1914 case IDC_FILETYPES_CHANGE
:
1915 pItem
= FindSelectedItem(GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
));
1918 Info
.oaifInFlags
= OAIF_ALLOW_REGISTRATION
| OAIF_REGISTER_EXT
;
1919 Info
.pcszClass
= pItem
->FileExtension
;
1920 SHOpenWithDialog(hwndDlg
, &Info
);
1927 lppl
= (LPNMLISTVIEW
) lParam
;
1929 if (lppl
->hdr
.code
== LVN_ITEMCHANGING
)
1931 ZeroMemory(&lvItem
, sizeof(LVITEM
));
1932 lvItem
.mask
= LVIF_PARAM
;
1933 lvItem
.iItem
= lppl
->iItem
;
1934 if (!SendMessageW(lppl
->hdr
.hwndFrom
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
))
1937 pItem
= (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
1941 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
1943 /* new focused item */
1944 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILS
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
1946 /* use default english format string */
1947 wcscpy(FormatBuffer
, L
"Details for '%s' extension");
1951 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1]);
1953 SetDlgItemTextW(hwndDlg
, IDC_FILETYPES_DETAILS_GROUPBOX
, Buffer
);
1955 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILSADV
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
1957 /* use default english format string */
1958 wcscpy(FormatBuffer
, L
"Files with extension '%s' are of type '%s'. To change settings that affect all '%s' files, click Advanced.");
1961 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1], &pItem
->FileDescription
[0], &pItem
->FileDescription
[0]);
1963 SetDlgItemTextW(hwndDlg
, IDC_FILETYPES_DESCRIPTION
, Buffer
);
1965 /* Enable the Delete button */
1966 if (pItem
->EditFlags
& 0x00000010) // FTA_NoRemove
1967 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILETYPES_DELETE
), FALSE
);
1969 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILETYPES_DELETE
), TRUE
);
1972 else if (lppl
->hdr
.code
== PSN_SETACTIVE
)
1974 /* On page activation, set the focus to the listview */
1975 SetFocus(GetDlgItem(hwndDlg
, IDC_FILETYPES_LISTVIEW
));
1985 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
1987 PROPSHEETHEADERW pinfo
;
1988 HPROPSHEETPAGE hppages
[3];
1989 HPROPSHEETPAGE hpage
;
1991 WCHAR szOptions
[100];
1993 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL
, FolderOptionsGeneralDlg
, 0, NULL
);
1995 hppages
[num_pages
++] = hpage
;
1997 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW
, FolderOptionsViewDlg
, 0, NULL
);
1999 hppages
[num_pages
++] = hpage
;
2001 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES
, FolderOptionsFileTypesDlg
, 0, NULL
);
2003 hppages
[num_pages
++] = hpage
;
2005 szOptions
[0] = L
'\0';
2006 LoadStringW(shell32_hInstance
, IDS_FOLDER_OPTIONS
, szOptions
, sizeof(szOptions
) / sizeof(WCHAR
));
2007 szOptions
[(sizeof(szOptions
)/sizeof(WCHAR
))-1] = L
'\0';
2009 memset(&pinfo
, 0x0, sizeof(PROPSHEETHEADERW
));
2010 pinfo
.dwSize
= sizeof(PROPSHEETHEADERW
);
2011 pinfo
.dwFlags
= PSH_NOCONTEXTHELP
;
2012 pinfo
.nPages
= num_pages
;
2013 pinfo
.phpage
= hppages
;
2014 pinfo
.pszCaption
= szOptions
;
2016 PropertySheetW(&pinfo
);
2021 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
2026 ShowFolderOptionsDialog(hWnd
, hInst
);
2029 // show taskbar options dialog
2030 FIXME("notify explorer to show taskbar options dialog");
2031 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
2034 FIXME("unrecognized options id %d\n", fOptions
);
2038 /*************************************************************************
2039 * Options_RunDLL (SHELL32.@)
2041 EXTERN_C VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
2043 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
2046 /*************************************************************************
2047 * Options_RunDLLA (SHELL32.@)
2049 EXTERN_C VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
2051 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
2054 /*************************************************************************
2055 * Options_RunDLLW (SHELL32.@)
2057 EXTERN_C VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
2059 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);