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
);
89 FolderOptionsGeneralDlg(
101 InitializeFolderOptionsListCtrl(HWND hwndDlg
)
108 hDlgCtrl
= GetDlgItem(hwndDlg
, 14003);
110 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
112 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
114 GetClientRect(hDlgCtrl
, &clientRect
);
115 ZeroMemory(&col
, sizeof(LV_COLUMN
));
116 col
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_FMT
;
118 col
.pszText
= szName
;
119 col
.fmt
= LVCFMT_LEFT
;
120 col
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
121 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
129 FolderOptionsViewDlg(
139 InitializeFolderOptionsListCtrl(hwndDlg
);
149 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
155 int columnSize
= 140;
158 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
160 /* default to english */
161 wcscpy(szName
, L
"Extensions");
164 /* make sure its null terminated */
165 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
167 GetClientRect(hDlgCtrl
, &clientRect
);
168 ZeroMemory(&col
, sizeof(LV_COLUMN
));
169 columnSize
= 140; //FIXME
171 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_FMT
;
172 col
.fmt
= LVCFMT_FIXED_WIDTH
;
173 col
.cx
= columnSize
| LVCFMT_LEFT
;
174 col
.cchTextMax
= wcslen(szName
);
175 col
.pszText
= szName
;
176 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&col
);
178 if (!LoadStringW(shell32_hInstance
, IDS_FILE_TYPES
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
180 /* default to english */
181 wcscpy(szName
, L
"File Types");
182 ERR("Failed to load localized string!\n");
186 col
.cx
= clientRect
.right
- clientRect
.left
- columnSize
;
187 col
.cchTextMax
= wcslen(szName
);
188 col
.pszText
= szName
;
189 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&col
);
191 /* set full select style */
192 dwStyle
= (DWORD
) SendMessage(hDlgCtrl
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
193 dwStyle
= dwStyle
| LVS_EX_FULLROWSELECT
;
194 SendMessage(hDlgCtrl
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, dwStyle
);
198 FindItem(HWND hDlgCtrl
, WCHAR
* ItemName
)
200 LVFINDINFOW findInfo
;
201 ZeroMemory(&findInfo
, sizeof(LVFINDINFOW
));
203 findInfo
.flags
= LVFI_STRING
;
204 findInfo
.psz
= ItemName
;
205 return ListView_FindItem(hDlgCtrl
, 0, &findInfo
);
210 InsertFileType(HWND hDlgCtrl
, WCHAR
* szName
, PINT iItem
, WCHAR
* szFile
)
212 PFOLDER_FILE_TYPE_ENTRY Entry
;
218 if (szName
[0] != L
'.')
220 /* FIXME handle URL protocol handlers */
224 /* allocate file type entry */
225 Entry
= (PFOLDER_FILE_TYPE_ENTRY
)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY
));
231 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szName
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
233 HeapFree(GetProcessHeap(), 0, Entry
);
237 /* FIXME check for duplicates */
239 /* query for the default key */
240 dwSize
= sizeof(Entry
->ClassKey
);
241 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->ClassKey
, &dwSize
) != ERROR_SUCCESS
)
243 /* no link available */
244 Entry
->ClassKey
[0] = 0;
247 if (Entry
->ClassKey
[0])
250 /* try open linked key */
251 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, Entry
->ClassKey
, 0, KEY_READ
, &hTemp
) == ERROR_SUCCESS
)
259 /* read friendly type name */
260 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", Entry
->FileDescription
, sizeof(Entry
->FileDescription
), NULL
, 0, NULL
) != ERROR_SUCCESS
)
262 /* read file description */
263 dwSize
= sizeof(Entry
->FileDescription
);
264 Entry
->FileDescription
[0] = 0;
266 /* read default key */
267 RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)Entry
->FileDescription
, &dwSize
);
270 /* Read the EditFlags value */
271 Entry
->EditFlags
= 0;
272 if (!RegQueryValueExW(hKey
, L
"EditFlags", NULL
, &dwType
, NULL
, &dwSize
))
274 if ((dwType
== REG_DWORD
|| dwType
== REG_BINARY
) && dwSize
== sizeof(DWORD
))
275 RegQueryValueExW(hKey
, L
"EditFlags", NULL
, NULL
, (LPBYTE
)&Entry
->EditFlags
, &dwSize
);
281 /* Do not add excluded entries */
282 if (Entry
->EditFlags
& 0x00000001) //FTA_Exclude
284 HeapFree(GetProcessHeap(), 0, Entry
);
288 /* convert extension to upper case */
289 wcscpy(Entry
->FileExtension
, szName
);
290 _wcsupr(Entry
->FileExtension
);
292 if (!Entry
->FileDescription
[0])
294 /* construct default 'FileExtensionFile' by formatting the uppercase extension
295 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
297 StringCchPrintf(Entry
->FileDescription
, _countof(Entry
->FileDescription
), szFile
, &Entry
->FileExtension
[1]);
300 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
301 lvItem
.mask
= LVIF_TEXT
| LVIF_PARAM
;
303 lvItem
.pszText
= &Entry
->FileExtension
[1];
304 lvItem
.iItem
= *iItem
;
305 lvItem
.lParam
= (LPARAM
)Entry
;
306 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
);
308 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
309 lvItem
.mask
= LVIF_TEXT
;
310 lvItem
.pszText
= Entry
->FileDescription
;
311 lvItem
.iItem
= *iItem
;
313 ListView_SetItem(hDlgCtrl
, &lvItem
);
321 ListViewCompareProc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
323 PFOLDER_FILE_TYPE_ENTRY Entry1
, Entry2
;
326 Entry1
= (PFOLDER_FILE_TYPE_ENTRY
)lParam1
;
327 Entry2
= (PFOLDER_FILE_TYPE_ENTRY
)lParam2
;
329 x
= wcsicmp(Entry1
->FileExtension
, Entry2
->FileExtension
);
333 return wcsicmp(Entry1
->FileDescription
, Entry2
->FileDescription
);
337 PFOLDER_FILE_TYPE_ENTRY
338 InitializeFileTypesListCtrl(HWND hwndDlg
)
348 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
349 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
352 if (!LoadStringW(shell32_hInstance
, IDS_FILE_EXT_TYPE
, szFile
, _countof(szFile
)))
354 /* default to english */
355 wcscpy(szFile
, L
"%s File");
357 szFile
[(_countof(szFile
)) - 1] = 0;
359 dwName
= _countof(szName
);
361 while (RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
363 InsertFileType(hDlgCtrl
, szName
, &iItem
, szFile
);
364 dwName
= _countof(szName
);
367 /* Leave if the list is empty */
372 ListView_SortItems(hDlgCtrl
, ListViewCompareProc
, NULL
);
374 /* select first item */
375 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
376 lvItem
.mask
= LVIF_STATE
;
377 lvItem
.stateMask
= (UINT
)-1;
378 lvItem
.state
= LVIS_FOCUSED
| LVIS_SELECTED
;
380 ListView_SetItem(hDlgCtrl
, &lvItem
);
382 lvItem
.mask
= LVIF_PARAM
;
383 ListView_GetItem(hDlgCtrl
, &lvItem
);
385 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
389 PFOLDER_FILE_TYPE_ENTRY
396 Count
= ListView_GetItemCount(hDlgCtrl
);
398 for (Index
= 0; Index
< Count
; Index
++)
400 ZeroMemory(&lvItem
, sizeof(LVITEM
));
401 lvItem
.mask
= LVIF_PARAM
| LVIF_STATE
;
402 lvItem
.iItem
= Index
;
403 lvItem
.stateMask
= (UINT
) - 1;
405 if (ListView_GetItem(hDlgCtrl
, &lvItem
))
407 if (lvItem
.state
& LVIS_SELECTED
)
408 return (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
417 FolderOptionsFileTypesDlg(
425 WCHAR Buffer
[255], FormatBuffer
[255];
426 PFOLDER_FILE_TYPE_ENTRY pItem
;
432 pItem
= InitializeFileTypesListCtrl(hwndDlg
);
434 /* Disable the Delete button if the listview is empty or
435 the selected item should not be deleted by the user */
436 if (pItem
== NULL
|| (pItem
->EditFlags
& 0x00000010)) // FTA_NoRemove
437 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
441 switch(LOWORD(wParam
))
444 pItem
= FindSelectedItem(GetDlgItem(hwndDlg
, 14000));
447 Info
.oaifInFlags
= OAIF_ALLOW_REGISTRATION
| OAIF_REGISTER_EXT
;
448 Info
.pcszClass
= pItem
->FileExtension
;
449 SHOpenWithDialog(hwndDlg
, &Info
);
456 lppl
= (LPNMLISTVIEW
) lParam
;
458 if (lppl
->hdr
.code
== LVN_ITEMCHANGING
)
460 ZeroMemory(&lvItem
, sizeof(LVITEM
));
461 lvItem
.mask
= LVIF_PARAM
;
462 lvItem
.iItem
= lppl
->iItem
;
463 if (!SendMessageW(lppl
->hdr
.hwndFrom
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
))
466 pItem
= (PFOLDER_FILE_TYPE_ENTRY
)lvItem
.lParam
;
470 if (!(lppl
->uOldState
& LVIS_FOCUSED
) && (lppl
->uNewState
& LVIS_FOCUSED
))
472 /* new focused item */
473 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILS
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
475 /* use default english format string */
476 wcscpy(FormatBuffer
, L
"Details for '%s' extension");
480 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1]);
482 SetDlgItemTextW(hwndDlg
, 14003, Buffer
);
484 if (!LoadStringW(shell32_hInstance
, IDS_FILE_DETAILSADV
, FormatBuffer
, sizeof(FormatBuffer
) / sizeof(WCHAR
)))
486 /* use default english format string */
487 wcscpy(FormatBuffer
, L
"Files with extension '%s' are of type '%s'. To change settings that affect all '%s' files, click Advanced.");
490 swprintf(Buffer
, FormatBuffer
, &pItem
->FileExtension
[1], &pItem
->FileDescription
[0], &pItem
->FileDescription
[0]);
492 SetDlgItemTextW(hwndDlg
, 14007, Buffer
);
494 /* Enable the Delete button */
495 if (pItem
->EditFlags
& 0x00000010) // FTA_NoRemove
496 EnableWindow(GetDlgItem(hwndDlg
, 14002), FALSE
);
498 EnableWindow(GetDlgItem(hwndDlg
, 14002), TRUE
);
501 else if (lppl
->hdr
.code
== PSN_SETACTIVE
)
503 /* On page activation, set the focus to the listview */
504 SetFocus(GetDlgItem(hwndDlg
, 14000));
514 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
516 PROPSHEETHEADERW pinfo
;
517 HPROPSHEETPAGE hppages
[3];
518 HPROPSHEETPAGE hpage
;
520 WCHAR szOptions
[100];
522 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL
, FolderOptionsGeneralDlg
, 0, NULL
);
524 hppages
[num_pages
++] = hpage
;
526 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW
, FolderOptionsViewDlg
, 0, NULL
);
528 hppages
[num_pages
++] = hpage
;
530 hpage
= SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES
, FolderOptionsFileTypesDlg
, 0, NULL
);
532 hppages
[num_pages
++] = hpage
;
534 szOptions
[0] = L
'\0';
535 LoadStringW(shell32_hInstance
, IDS_FOLDER_OPTIONS
, szOptions
, sizeof(szOptions
) / sizeof(WCHAR
));
536 szOptions
[(sizeof(szOptions
)/sizeof(WCHAR
))-1] = L
'\0';
538 memset(&pinfo
, 0x0, sizeof(PROPSHEETHEADERW
));
539 pinfo
.dwSize
= sizeof(PROPSHEETHEADERW
);
540 pinfo
.dwFlags
= PSH_NOCONTEXTHELP
;
541 pinfo
.nPages
= num_pages
;
542 pinfo
.phpage
= hppages
;
543 pinfo
.pszCaption
= szOptions
;
545 PropertySheetW(&pinfo
);
550 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
555 ShowFolderOptionsDialog(hWnd
, hInst
);
558 // show taskbar options dialog
559 FIXME("notify explorer to show taskbar options dialog");
560 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
563 FIXME("unrecognized options id %d\n", fOptions
);
567 /*************************************************************************
568 * Options_RunDLL (SHELL32.@)
570 EXTERN_C VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
572 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
575 /*************************************************************************
576 * Options_RunDLLA (SHELL32.@)
578 EXTERN_C VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
580 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
583 /*************************************************************************
584 * Options_RunDLLW (SHELL32.@)
586 EXTERN_C VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
588 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);