2 * Open With Context Menu extension
4 * Copyright 2007 Johannes Anderwald <janderwald@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
24 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
41 WCHAR szFolderPath
[MAX_PATH
];
42 }FOLDER_PROPERTIES_CONTEXT
, *PFOLDER_PROPERTIES_CONTEXT
;
48 }FOLDER_VIEW_ENTRY
, PFOLDER_VIEW_ENTRY
;
50 static FOLDER_VIEW_ENTRY s_Options[] =
52 { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
53 { L"AutoCheckSelect", -1 },
54 { L"ClassicViewState", -1 },
55 { L"DontPrettyPath", -1 },
57 { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
58 { L"FriendlyTree", -1 },
60 { L"HideFileExt", IDS_HIDEFILEEXT },
63 { L"ListviewAlphaSelect", -1},
64 { L"ListviewShadow", -1},
65 { L"ListviewWatermark", -1},
66 { L"MapNetDrvBtn", -1},
67 { L"PersistBrowsers", -1},
68 { L"SeperateProcess", IDS_SEPERATEPROCESS},
69 { L"ServerAdminUI", -1},
70 { L"SharingWizardOn", IDS_USESHAREWIZARD},
71 { L"ShowCompColor", IDS_COMPCOLOR},
72 { L"ShowInfoTip", IDS_SHOWINFOTIP},
73 { L"ShowPreviewHandlers", -1},
74 { L"ShowSuperHidden", IDS_HIDEOSFILES},
75 { L"ShowTypeOverlay", -1},
76 { L"Start_ShowMyGames", -1},
77 { L"StartMenuInit", -1},
78 { L"SuperHidden", -1},
89 FolderOptionsGeneralDlg(
104 InitializeFolderOptionsListCtrl(HWND hwndDlg
)
111 hDlgCtrl
= GetDlgItem(hwndDlg
, 14003);
113 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
115 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
117 GetClientRect(hDlgCtrl
, &clientRect
);
118 ZeroMemory(&col
, sizeof(LV_COLUMN
));
119 col
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_FMT
;
121 col
.pszText
= szName
;
122 col
.fmt
= LVCFMT_LEFT
;
123 col
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
124 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
133 FolderOptionsViewDlg(
143 InitializeFolderOptionsListCtrl(hwndDlg
);
152 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
158 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
160 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
162 GetClientRect(hDlgCtrl
, &clientRect
);
163 ZeroMemory(&col
, sizeof(LV_COLUMN
));
164 col
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_FMT
;
166 col
.pszText
= szName
;
167 col
.fmt
= LVCFMT_LEFT
;
168 col
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
169 (void)SendMessageW(hDlgCtrl
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&col
);
172 FindItem(HWND hDlgCtrl
, WCHAR
* ItemName
)
174 LVFINDINFOW findInfo
;
175 ZeroMemory(&findInfo
, sizeof(LVFINDINFOW
));
177 findInfo
.flags
= LVFI_STRING
;
178 findInfo
.psz
= ItemName
;
179 return ListView_FindItem(hDlgCtrl
, 0, &findInfo
);
183 InsertFileType(HWND hDlgCtrl
, WCHAR
* szName
, DWORD Size
, INT iItem
)
190 if (FindItem(hDlgCtrl
, szName
) != -1)
193 wcscpy(szPath
, szName
);
195 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szPath
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
197 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", szName
, Size
, NULL
, 0, NULL
) != ERROR_SUCCESS
)
200 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)szName
, &dwSize
) != ERROR_SUCCESS
)
202 wcscpy(szName
, szPath
);
206 szName
[(Size
/sizeof(WCHAR
))-1] = 0;
208 wcscat(szPath
, L
"\\shell");
210 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
211 lvItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
;
212 lvItem
.state
= LVIS_SELECTED
;
213 lvItem
.pszText
= szName
;
214 lvItem
.iItem
= iItem
;
216 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szPath
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
219 (void)SendMessageW(hDlgCtrl
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
);
225 InitializeFileTypesListCtrl(HWND hwndDlg
)
233 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
234 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
236 dwName
= sizeof(szName
) / sizeof(WCHAR
);
238 while(RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
240 InsertFileType(hDlgCtrl
, szName
, sizeof(szName
), iItem
++);
241 dwName
= sizeof(szName
) / sizeof(WCHAR
);
249 FolderOptionsFileTypesDlg(
259 InitializeFileTypesListCtrl(hwndDlg
);
268 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
270 PROPSHEETHEADERW pinfo
;
271 HPROPSHEETPAGE hppages
[3];
272 HPROPSHEETPAGE hpage
;
274 WCHAR szOptions
[100];
276 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_GENERAL_DLG", FolderOptionsGeneralDlg
, 0, NULL
);
278 hppages
[num_pages
++] = hpage
;
280 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_VIEW_DLG", FolderOptionsViewDlg
, 0, NULL
);
282 hppages
[num_pages
++] = hpage
;
284 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_FILETYPES_DLG", FolderOptionsFileTypesDlg
, 0, NULL
);
286 hppages
[num_pages
++] = hpage
;
288 szOptions
[0] = L
'\0';
289 LoadStringW(shell32_hInstance
, IDS_FOLDER_OPTIONS
, szOptions
, sizeof(szOptions
) / sizeof(WCHAR
));
290 szOptions
[(sizeof(szOptions
)/sizeof(WCHAR
))-1] = L
'\0';
292 memset(&pinfo
, 0x0, sizeof(PROPSHEETHEADERW
));
293 pinfo
.dwSize
= sizeof(PROPSHEETHEADERW
);
294 pinfo
.dwFlags
= PSH_NOCONTEXTHELP
;
295 pinfo
.nPages
= num_pages
;
296 pinfo
.u3
.phpage
= hppages
;
297 pinfo
.pszCaption
= szOptions
;
299 PropertySheetW(&pinfo
);
303 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
308 ShowFolderOptionsDialog(hWnd
, hInst
);
311 // show taskbar options dialog
312 FIXME("notify explorer to show taskbar options dialog");
313 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
316 FIXME("unrecognized options id %d\n", fOptions
);
320 /*************************************************************************
321 * Options_RunDLL (SHELL32.@)
323 VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
325 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
327 /*************************************************************************
328 * Options_RunDLLA (SHELL32.@)
330 VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
332 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
335 /*************************************************************************
336 * Options_RunDLLW (SHELL32.@)
338 VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
340 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);
345 CountFolderAndFiles(LPVOID lParam
)
347 WIN32_FIND_DATAW FindData
;
352 PFOLDER_PROPERTIES_CONTEXT pContext
= (PFOLDER_PROPERTIES_CONTEXT
) lParam
;
354 pOffset
= PathAddBackslashW(pContext
->szFolderPath
);
358 Length
= pOffset
- pContext
->szFolderPath
;
360 wcscpy(pOffset
, L
"*.*");
361 hFile
= FindFirstFileW(pContext
->szFolderPath
, &FindData
);
362 if (hFile
== INVALID_HANDLE_VALUE
)
367 ret
= FindNextFileW(hFile
, &FindData
);
370 if (FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
372 if (FindData
.cFileName
[0] == L
'.' && FindData
.cFileName
[1] == L
'.' &&
373 FindData
.cFileName
[2] == L
'\0')
377 wcscpy(pOffset
, FindData
.cFileName
);
378 CountFolderAndFiles((LPVOID
)pContext
);
384 pContext
->bSize
.u
.LowPart
+= FindData
.nFileSizeLow
;
385 pContext
->bSize
.u
.HighPart
+= FindData
.nFileSizeHigh
;
388 else if (GetLastError() == ERROR_NO_MORE_FILES
)
400 InitializeFolderGeneralDlg(PFOLDER_PROPERTIES_CONTEXT pContext
)
403 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute
;
406 WCHAR szBuffer
[MAX_PATH
+5];
407 WCHAR szFormat
[30] = {0};
409 static const WCHAR wFormat
[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
411 pFolderName
= wcsrchr(pContext
->szFolderPath
, L
'\\');
415 /* set folder name */
416 SendDlgItemMessageW(pContext
->hwndDlg
, 14001, WM_SETTEXT
, 0, (LPARAM
) (pFolderName
+ 1));
417 /* set folder location */
418 pFolderName
[0] = L
'\0';
419 if (wcslen(pContext
->szFolderPath
) == 2)
421 /* folder is located at root */
422 WCHAR szDrive
[4] = {L
'C',L
':',L
'\\',L
'\0'};
423 szDrive
[0] = pContext
->szFolderPath
[0];
424 SendDlgItemMessageW(pContext
->hwndDlg
, 14007, WM_SETTEXT
, 0, (LPARAM
) szDrive
);
428 SendDlgItemMessageW(pContext
->hwndDlg
, 14007, WM_SETTEXT
, 0, (LPARAM
) pContext
->szFolderPath
);
430 pFolderName
[0] = L
'\\';
431 /* get folder properties */
432 if (GetFileAttributesExW(pContext
->szFolderPath
, GetFileExInfoStandard
, (LPVOID
)&FolderAttribute
))
434 if (FolderAttribute
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
436 /* check readonly button */
437 SendDlgItemMessage(pContext
->hwndDlg
, 14021, BM_SETCHECK
, BST_CHECKED
, 0);
440 if (FolderAttribute
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
442 /* check hidden button */
443 SendDlgItemMessage(pContext
->hwndDlg
, 14022, BM_SETCHECK
, BST_CHECKED
, 0);
446 if (FileTimeToLocalFileTime(&FolderAttribute
.ftCreationTime
, &ft
))
448 FileTimeToSystemTime(&ft
, &dt
);
449 swprintf (szBuffer
, wFormat
, dt
.wDay
, dt
.wMonth
, dt
.wYear
, dt
.wHour
, dt
.wMinute
);
450 SendDlgItemMessageW(pContext
->hwndDlg
, 14015, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
453 /* now enumerate enumerate contents */
454 wcscpy(szBuffer
, pContext
->szFolderPath
);
455 CountFolderAndFiles((LPVOID
)pContext
);
456 wcscpy(pContext
->szFolderPath
, szBuffer
);
457 /* set folder details */
458 LoadStringW(shell32_hInstance
, IDS_FILE_FOLDER
, szFormat
, sizeof(szFormat
)/sizeof(WCHAR
));
459 szFormat
[(sizeof(szFormat
)/sizeof(WCHAR
))-1] = L
'\0';
460 swprintf(szBuffer
, szFormat
, pContext
->cFiles
, pContext
->cFolder
);
461 SendDlgItemMessageW(pContext
->hwndDlg
, 14011, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
463 if (StrFormatByteSizeW(pContext
->bSize
.QuadPart
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
465 /* store folder size */
466 SendDlgItemMessageW(pContext
->hwndDlg
, 14009, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
473 FolderPropertiesGeneralDlg(
480 LPPROPSHEETPAGEW ppsp
;
481 PFOLDER_PROPERTIES_CONTEXT pContext
;
483 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute
;
491 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
494 hIcon
= LoadIconW(shell32_hInstance
, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPEN
));
496 SendDlgItemMessageW(hwndDlg
, 14000, STM_SETICON
, (WPARAM
)hIcon
, 0);
498 pContext
= SHAlloc(sizeof(FOLDER_PROPERTIES_CONTEXT
));
501 ZeroMemory(pContext
, sizeof(FOLDER_PROPERTIES_CONTEXT
));
502 pContext
->hwndDlg
= hwndDlg
;
503 wcscpy(pContext
->szFolderPath
, (LPWSTR
)ppsp
->lParam
);
504 SetWindowLongPtr(hwndDlg
, DWL_USER
, (LONG_PTR
)pContext
);
505 InitializeFolderGeneralDlg(pContext
);
509 if (HIWORD(wParam
) == BN_CLICKED
)
511 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
515 pContext
= (PFOLDER_PROPERTIES_CONTEXT
)GetWindowLong(hwndDlg
, DWL_USER
);
516 SHFree((LPVOID
)pContext
);
519 pContext
= (PFOLDER_PROPERTIES_CONTEXT
)GetWindowLong(hwndDlg
, DWL_USER
);
520 lppsn
= (LPPSHNOTIFY
) lParam
;
521 if (lppsn
->hdr
.code
== PSN_APPLY
)
523 if (GetFileAttributesExW(pContext
->szFolderPath
, GetFileExInfoStandard
, (LPVOID
)&FolderAttribute
))
525 res
= SendDlgItemMessageW(hwndDlg
, 14021, BM_GETCHECK
, 0, 0);
526 if (res
== BST_CHECKED
)
527 FolderAttribute
.dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
529 FolderAttribute
.dwFileAttributes
&= (~FILE_ATTRIBUTE_READONLY
);
531 res
= SendDlgItemMessageW(hwndDlg
, 14022, BM_GETCHECK
, 0, 0);
532 if (res
== BST_CHECKED
)
533 FolderAttribute
.dwFileAttributes
|= FILE_ATTRIBUTE_HIDDEN
;
535 FolderAttribute
.dwFileAttributes
&= (~FILE_ATTRIBUTE_HIDDEN
);
537 Attribute
= FolderAttribute
.dwFileAttributes
&
538 (FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_NORMAL
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
|FILE_ATTRIBUTE_TEMPORARY
);
540 SetFileAttributesW(pContext
->szFolderPath
, Attribute
);
542 SetWindowLong( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
553 FolderAddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
555 PROPSHEETHEADERW
*ppsh
= (PROPSHEETHEADERW
*)lParam
;
556 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
558 ppsh
->u3
.phpage
[ppsh
->nPages
++] = hpage
;
565 SH_ShowFolderProperties(LPWSTR pwszFolder
)
567 HPROPSHEETPAGE hppages
[MAX_PROPERTY_SHEET_PAGE
];
568 HPROPSHEETPAGE hpage
;
569 PROPSHEETHEADERW psh
;
571 WCHAR szName
[MAX_PATH
] = {0};
575 if (!PathIsDirectoryW(pwszFolder
))
578 pFolderName
= wcsrchr(pwszFolder
, L
'\\');
582 wcscpy(szName
, pFolderName
+ 1);
584 hpage
= SH_CreatePropertySheetPage("SHELL_FOLDER_GENERAL_DLG", FolderPropertiesGeneralDlg
, (LPARAM
)pwszFolder
, NULL
);
588 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
589 hppages
[psh
.nPages
] = hpage
;
591 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
592 psh
.dwFlags
= PSH_PROPTITLE
;
593 psh
.hwndParent
= NULL
;
594 psh
.u3
.phpage
= hppages
;
595 psh
.pszCaption
= szName
;
597 hpsx
= SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT
,
599 MAX_PROPERTY_SHEET_PAGE
-1);
601 SHAddFromPropSheetExtArray(hpsx
,
602 (LPFNADDPROPSHEETPAGE
)FolderAddPropSheetPageProc
,
605 ret
= PropertySheetW(&psh
);