2 * Open With Context Menu extension
4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 WINE_DEFAULT_DEBUG_CHANNEL (fprop
);
25 #define MAX_PROPERTY_SHEET_PAGE (32)
28 /// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
29 /// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210
30 /// Verbs: Open / RunAs
31 /// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0
33 /// ShellFolder Attributes: 0x0
37 WCHAR FileExtension
[30];
38 WCHAR FileDescription
[100];
39 WCHAR ClassKey
[MAX_PATH
];
41 } FOLDER_FILE_TYPE_ENTRY
, *PFOLDER_FILE_TYPE_ENTRY
;
47 } FOLDER_VIEW_ENTRY
, PFOLDER_VIEW_ENTRY
;
49 static FOLDER_VIEW_ENTRY s_Options[] =
51 { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
52 { L"AutoCheckSelect", -1 },
53 { L"ClassicViewState", -1 },
54 { L"DontPrettyPath", -1 },
56 { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
57 { L"FriendlyTree", -1 },
59 { L"HideFileExt", IDS_HIDEFILEEXT },
62 { L"ListviewAlphaSelect", -1},
63 { L"ListviewShadow", -1},
64 { L"ListviewWatermark", -1},
65 { L"MapNetDrvBtn", -1},
66 { L"PersistBrowsers", -1},
67 { L"SeperateProcess", IDS_SEPERATEPROCESS},
68 { L"ServerAdminUI", -1},
69 { L"SharingWizardOn", IDS_USESHAREWIZARD},
70 { L"ShowCompColor", IDS_COMPCOLOR},
71 { L"ShowInfoTip", IDS_SHOWINFOTIP},
72 { L"ShowPreviewHandlers", -1},
73 { L"ShowSuperHidden", IDS_HIDEOSFILES},
74 { L"ShowTypeOverlay", -1},
75 { L"Start_ShowMyGames", -1},
76 { L"StartMenuInit", -1},
77 { L"SuperHidden", -1},
85 EXTERN_C HPSXA WINAPI
SHCreatePropSheetExtArrayEx(HKEY hKey
, LPCWSTR pszSubKey
, UINT max_iface
, IDataObject
*pDataObj
);
88 UpdateGeneralIcons(HWND hDlg
)
90 HWND hwndTaskIcon
, hwndFolderIcon
, hwndClickIcon
;
91 HICON hTaskIcon
= NULL
, hFolderIcon
= NULL
, hClickIcon
= NULL
;
92 LPTSTR lpTaskIconName
= NULL
, lpFolderIconName
= NULL
, lpClickIconName
= NULL
;
94 // show task setting icon
95 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_COMMONTASKS
) == BST_CHECKED
)
96 lpTaskIconName
= MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS
);
97 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_CLASSICFOLDERS
) == BST_CHECKED
)
98 lpTaskIconName
= MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS
);
102 hTaskIcon
= (HICON
)LoadImage(shell32_hInstance
,
110 hwndTaskIcon
= GetDlgItem(hDlg
,
111 IDC_FOLDER_OPTIONS_TASKICON
);
114 SendMessage(hwndTaskIcon
,
122 // show Folder setting icons
123 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_SAMEWINDOW
) == BST_CHECKED
)
124 lpFolderIconName
= MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW
);
125 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_OWNWINDOW
) == BST_CHECKED
)
126 lpFolderIconName
= MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW
);
128 if (lpFolderIconName
)
130 hFolderIcon
= (HICON
)LoadImage(shell32_hInstance
,
138 hwndFolderIcon
= GetDlgItem(hDlg
,
139 IDC_FOLDER_OPTIONS_FOLDERICON
);
142 SendMessage(hwndFolderIcon
,
145 (LPARAM
)hFolderIcon
);
150 // Show click setting icon
151 if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_SINGLECLICK
) == BST_CHECKED
)
152 lpClickIconName
= MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN
);
153 else if(IsDlgButtonChecked(hDlg
, IDC_FOLDER_OPTIONS_DOUBLECLICK
) == BST_CHECKED
)
154 lpClickIconName
= MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN
);
158 hClickIcon
= (HICON
)LoadImage(shell32_hInstance
,
166 hwndClickIcon
= GetDlgItem(hDlg
,
167 IDC_FOLDER_OPTIONS_CLICKICON
);
170 SendMessage(hwndClickIcon
,
180 DeleteObject(hTaskIcon
);
182 DeleteObject(hFolderIcon
);
184 DeleteObject(hClickIcon
);
191 FolderOptionsGeneralDlg(
205 switch (LOWORD(wParam
))
207 case IDC_FOLDER_OPTIONS_COMMONTASKS
:
208 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS
:
209 case IDC_FOLDER_OPTIONS_SAMEWINDOW
:
210 case IDC_FOLDER_OPTIONS_OWNWINDOW
:
211 case IDC_FOLDER_OPTIONS_SINGLECLICK
:
212 case IDC_FOLDER_OPTIONS_DOUBLECLICK
:
213 if (HIWORD(wParam
) == BN_CLICKED
)
215 UpdateGeneralIcons(hwndDlg
);
217 /* Enable the 'Apply' button */
218 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
226 LPNMHDR pnmh
= (LPNMHDR
)lParam
;
250 InitializeFolderOptionsListCtrl(HWND hwndDlg
)
257 hDlgCtrl
= GetDlgItem(hwndDlg
, 14003);
259 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
261 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
263 GetClientRect(hDlgCtrl
, &clientRect
);
264 ZeroMemory(&col
, sizeof(LV_COLUMN
));
265 col
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_FMT
;
267 col
.pszText
= szName
;
268 col
.fmt
= LVCFMT_LEFT
;
269 col
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
270 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
278 FolderOptionsViewDlg(
288 InitializeFolderOptionsListCtrl(hwndDlg
);
298 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
304 int columnSize
= 140;
307 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
309 /* default to english */
310 wcscpy(szName
, L
"Extensions");
313 /* make sure its null terminated */
314 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
316 GetClientRect(hDlgCtrl
, &clientRect
);
317 ZeroMemory(&col
, sizeof(LV_COLUMN
));
318 columnSize
= 140; //FIXME
320 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_FMT
;
321 col
.fmt
= LVCFMT_FIXED_WIDTH
;
322 col
.cx
= columnSize
| LVCFMT_LEFT
;
323 col
.cchTextMax
= wcslen(szName
);
324 col
.pszText
= szName
;
325 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&col
);
327 if (!LoadStringW(shell32_hInstance
, IDS_FILE_TYPES
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
329 /* default to english */
330 wcscpy(szName
, L
"File Types");
331 ERR("Failed to load localized string!\n");
335 col
.cx
= clientRect
.right
- clientRect
.left
- columnSize
;
336 col
.cchTextMax
= wcslen(szName
);
337 col
.pszText
= szName
;
338 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&col
);
340 /* set full select style */
341 dwStyle
= (DWORD
) SendMessage(hDlgCtrl
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
342 dwStyle
= dwStyle
| LVS_EX_FULLROWSELECT
;
343 SendMessage(hDlgCtrl
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, dwStyle
);
347 FindItem(HWND hDlgCtrl
, WCHAR
* ItemName
)
349 LVFINDINFOW findInfo
;
350 ZeroMemory(&findInfo
, sizeof(LVFINDINFOW
));
352 findInfo
.flags
= LVFI_STRING
;
353 findInfo
.psz
= ItemName
;
354 return ListView_FindItem(hDlgCtrl
, 0, &findInfo
);
359 InsertFileType(HWND hDlgCtrl
, WCHAR
* szName
, PINT iItem
, WCHAR
* szFile
)
361 PFOLDER_FILE_TYPE_ENTRY Entry
;
367 if (szName
[0] != L
'.')
369 /* FIXME handle URL protocol handlers */
373 /* allocate file type entry */
374 Entry
= (PFOLDER_FILE_TYPE_ENTRY
)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY
));
380 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szName
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
382 HeapFree(GetProcessHeap(), 0, Entry
);
386 /* FIXME check for duplicates */
388 /* query for the default key */
389 dwSize
= sizeof(Entry
->ClassKey
);
390 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->ClassKey
, &dwSize
) != ERROR_SUCCESS
)
392 /* no link available */
393 Entry
->ClassKey
[0] = 0;
396 if (Entry
->ClassKey
[0])
399 /* try open linked key */
400 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, Entry
->ClassKey
, 0, KEY_READ
, &hTemp
) == ERROR_SUCCESS
)
408 /* read friendly type name */
409 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", Entry
->FileDescription
, sizeof(Entry
->FileDescription
), NULL
, 0, NULL
) != ERROR_SUCCESS
)
411 /* read file description */
412 dwSize
= sizeof(Entry
->FileDescription
);
413 Entry
->FileDescription
[0] = 0;
415 /* read default key */
416 RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->FileDescription
, &dwSize
);
419 /* Read the EditFlags value */
420 Entry
->EditFlags
= 0;
421 if (!RegQueryValueExW(hKey
, L
"EditFlags", NULL
, &dwType
, NULL
, &dwSize
))
423 if ((dwType
== REG_DWORD
|| dwType
== REG_BINARY
) && dwSize
== sizeof(DWORD
))
424 RegQueryValueExW(hKey
, L
"EditFlags", NULL
, NULL
, (LPBYTE
)&Entry
->EditFlags
, &dwSize
);
430 /* Do not add excluded entries */
431 if (Entry
->EditFlags
& 0x00000001) //FTA_Exclude
433 HeapFree(GetProcessHeap(), 0, Entry
);
437 /* convert extension to upper case */
438 wcscpy(Entry
->FileExtension
, szName
);
439 _wcsupr(Entry
->FileExtension
);
441 if (!Entry
->FileDescription
[0])
443 /* construct default 'FileExtensionFile' by formatting the uppercase extension
444 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
446 StringCchPrintf(Entry
->FileDescription
, _countof(Entry
->FileDescription
), szFile
, &Entry
->FileExtension
[1]);
449 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
450 lvItem
.mask
= LVIF_TEXT
| LVIF_PARAM
;
452 lvItem
.pszText
= &Entry
->FileExtension
[1];
453 lvItem
.iItem
= *iItem
;
454 lvItem
.lParam
= (LPARAM
)Entry
;
455 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
);
457 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
458 lvItem
.mask
= LVIF_TEXT
;
459 lvItem
.pszText
= Entry
->FileDescription
;
460 lvItem
.iItem
= *iItem
;
462 ListView_SetItem(hDlgCtrl
, &lvItem
);
470 ListViewCompareProc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
472 PFOLDER_FILE_TYPE_ENTRY Entry1
, Entry2
;
475 Entry1
= (PFOLDER_FILE_TYPE_ENTRY
)lParam1
;
476 Entry2
= (PFOLDER_FILE_TYPE_ENTRY
)lParam2
;
478 x
= wcsicmp(Entry1
->FileExtension
, Entry2
->FileExtension
);
482 return wcsicmp(Entry1
->FileDescription
, Entry2
->FileDescription
);
486 PFOLDER_FILE_TYPE_ENTRY
487 InitializeFileTypesListCtrl(HWND hwndDlg
)
497 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
498 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
501 if (!LoadStringW(shell32_hInstance
, IDS_FILE_EXT_TYPE
, szFile
, _countof(szFile
)))
503 /* default to english */
504 wcscpy(szFile
, L
"%s File");
506 szFile
[(_countof(szFile
)) - 1] = 0;
508 dwName
= _countof(szName
);
510 while (RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
512 InsertFileType(hDlgCtrl
, szName
, &iItem
, szFile
);
513 dwName
= _countof(szName
);
516 /* Leave if the list is empty */
521 ListView_SortItems(hDlgCtrl
, ListViewCompareProc
, NULL
);
523 /* select first item */
524 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
525 lvItem
.mask
= LVIF_STATE
;
526 lvItem
.stateMask
= (UINT
)-1;
527 lvItem
.state
= LVIS_FOCUSED
| LVIS_SELECTED
;
529 ListView_SetItem(hDlgCtrl
, &lvItem
);
531 lvItem
.mask
= LVIF_PARAM
;
532 ListView_GetItem(hDlgCtrl
, &lvItem
);
534 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
538 PFOLDER_FILE_TYPE_ENTRY
545 Count
= ListView_GetItemCount(hDlgCtrl
);
547 for (Index
= 0; Index
< Count
; Index
++)
549 ZeroMemory(&lvItem
, sizeof(LVITEM
));
550 lvItem
.mask
= LVIF_PARAM
| LVIF_STATE
;
551 lvItem
.iItem
= Index
;
552 lvItem
.stateMask
= (UINT
) - 1;
554 if (ListView_GetItem(hDlgCtrl
, &lvItem
))
556 if (lvItem
.state
& LVIS_SELECTED
)
557 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
566 FolderOptionsFileTypesDlg(
574 WCHAR Buffer
[255], FormatBuffer
[255];
575 PFOLDER_FILE_TYPE_ENTRY pItem
;
581 pItem
= InitializeFileTypesListCtrl(hwndDlg
);
583 /* Disable the Delete button if the listview is empty or
584 the selected item should not be deleted by the user */
585 if (pItem
== NULL
|| (pItem
->EditFlags
& 0x00000010)) // FTA_NoRemove
586 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
590 switch(LOWORD(wParam
))
593 pItem
= FindSelectedItem(GetDlgItem(hwndDlg
, 14000));
596 Info
.oaifInFlags
= OAIF_ALLOW_REGISTRATION
| OAIF_REGISTER_EXT
;
597 Info
.pcszClass
= pItem
->FileExtension
;
598 SHOpenWithDialog(hwndDlg
, &Info
);
605 lppl
= (LPNMLISTVIEW
) lParam
;
607 if (lppl
->hdr
.code
== LVN_ITEMCHANGING
)
609 ZeroMemory(&lvItem
, sizeof(LVITEM
));
610 lvItem
.mask
= LVIF_PARAM
;
611 lvItem
.iItem
= lppl
->iItem
;
612 if (!SendMessageW(lppl
->hdr
.hwndFrom
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
))
615 pItem
= (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
619 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
621 /* new focused item */
622 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILS
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
624 /* use default english format string */
625 wcscpy(FormatBuffer
, L
"Details for '%s' extension");
629 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1]);
631 SetDlgItemTextW(hwndDlg
, 14003, Buffer
);
633 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILSADV
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
635 /* use default english format string */
636 wcscpy(FormatBuffer
, L
"Files with extension '%s' are of type '%s'. To change settings that affect all '%s' files, click Advanced.");
639 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1], &pItem
->FileDescription
[0], &pItem
->FileDescription
[0]);
641 SetDlgItemTextW(hwndDlg
, 14007, Buffer
);
643 /* Enable the Delete button */
644 if (pItem
->EditFlags
& 0x00000010) // FTA_NoRemove
645 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
647 EnableWindow(GetDlgItem(hwndDlg
, 14002), TRUE
);
650 else if (lppl
->hdr
.code
== PSN_SETACTIVE
)
652 /* On page activation, set the focus to the listview */
653 SetFocus(GetDlgItem(hwndDlg
, 14000));
663 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
665 PROPSHEETHEADERW pinfo
;
666 HPROPSHEETPAGE hppages
[3];
667 HPROPSHEETPAGE hpage
;
669 WCHAR szOptions
[100];
671 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL
, FolderOptionsGeneralDlg
, 0, NULL
);
673 hppages
[num_pages
++] = hpage
;
675 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW
, FolderOptionsViewDlg
, 0, NULL
);
677 hppages
[num_pages
++] = hpage
;
679 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES
, FolderOptionsFileTypesDlg
, 0, NULL
);
681 hppages
[num_pages
++] = hpage
;
683 szOptions
[0] = L
'\0';
684 LoadStringW(shell32_hInstance
, IDS_FOLDER_OPTIONS
, szOptions
, sizeof(szOptions
) / sizeof(WCHAR
));
685 szOptions
[(sizeof(szOptions
)/sizeof(WCHAR
))-1] = L
'\0';
687 memset(&pinfo
, 0x0, sizeof(PROPSHEETHEADERW
));
688 pinfo
.dwSize
= sizeof(PROPSHEETHEADERW
);
689 pinfo
.dwFlags
= PSH_NOCONTEXTHELP
;
690 pinfo
.nPages
= num_pages
;
691 pinfo
.phpage
= hppages
;
692 pinfo
.pszCaption
= szOptions
;
694 PropertySheetW(&pinfo
);
699 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
704 ShowFolderOptionsDialog(hWnd
, hInst
);
707 // show taskbar options dialog
708 FIXME("notify explorer to show taskbar options dialog");
709 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
712 FIXME("unrecognized options id %d\n", fOptions
);
716 /*************************************************************************
717 * Options_RunDLL (SHELL32.@)
719 EXTERN_C VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
721 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
724 /*************************************************************************
725 * Options_RunDLLA (SHELL32.@)
727 EXTERN_C VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
729 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
732 /*************************************************************************
733 * Options_RunDLLW (SHELL32.@)
735 EXTERN_C VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
737 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);