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 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
27 #include "wine/debug.h"
32 #include "undocshell.h"
37 #include "shell32_main.h"
38 #include "shellfolder.h"
43 WINE_DEFAULT_DEBUG_CHANNEL (fprop
);
44 #define MAX_PROPERTY_SHEET_PAGE (32)
47 /// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
48 /// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210
49 /// Verbs: Open / RunAs
50 /// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0
52 /// ShellFolder Attributes: 0x0
60 WCHAR szFolderPath
[MAX_PATH
];
61 }FOLDER_PROPERTIES_CONTEXT
, *PFOLDER_PROPERTIES_CONTEXT
;
66 FolderOptionsGeneralDlg(
95 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl
)
101 if (!LoadStringW(shell32_hInstance
, IDS_COLUMN_EXTENSION
, szName
, sizeof(szName
) / sizeof(WCHAR
)))
103 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
105 GetClientRect(hDlgCtrl
, &clientRect
);
106 ZeroMemory(&col
, sizeof(LV_COLUMN
));
107 col
.mask
= LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_FMT
;
109 col
.pszText
= szName
;
110 col
.fmt
= LVCFMT_LEFT
;
111 col
.cx
= (clientRect
.right
- clientRect
.left
) - GetSystemMetrics(SM_CXVSCROLL
);
112 (void)ListView_InsertColumnW(hDlgCtrl
, 0, &col
);
115 FindItem(HWND hDlgCtrl
, WCHAR
* ItemName
)
117 LVFINDINFOW findInfo
;
118 ZeroMemory(&findInfo
, sizeof(LVFINDINFOW
));
120 findInfo
.flags
= LVFI_STRING
;
121 findInfo
.psz
= ItemName
;
122 return ListView_FindItem(hDlgCtrl
, 0, &findInfo
);
126 InsertFileType(HWND hDlgCtrl
, WCHAR
* szName
, DWORD Size
, INT iItem
)
133 if (FindItem(hDlgCtrl
, szName
) != -1)
136 wcscpy(szPath
, szName
);
138 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szPath
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
140 if (RegLoadMUIStringW(hKey
, L
"FriendlyTypeName", szName
, Size
, NULL
, 0, NULL
) != ERROR_SUCCESS
)
143 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)szName
, &dwSize
) != ERROR_SUCCESS
)
145 wcscpy(szName
, szPath
);
149 szName
[(Size
/sizeof(WCHAR
))-1] = 0;
151 wcscat(szPath
, L
"\\shell");
153 ZeroMemory(&lvItem
, sizeof(LVITEMW
));
154 lvItem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
;
155 lvItem
.state
= LVIS_SELECTED
;
156 lvItem
.pszText
= szName
;
157 lvItem
.iItem
= iItem
;
159 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szPath
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
162 (void)ListView_InsertItemW(hDlgCtrl
, &lvItem
);
168 InitializeFileTypesListCtrl(HWND hwndDlg
)
177 hDlgCtrl
= GetDlgItem(hwndDlg
, 14000);
178 InitializeFileTypesListCtrlColumns(hDlgCtrl
);
182 dwName
= sizeof(szName
) / sizeof(WCHAR
);
184 while(RegEnumKeyExW(HKEY_CLASSES_ROOT
, dwIndex
++, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
186 InsertFileType(hDlgCtrl
, szName
, sizeof(szName
), iItem
++);
187 dwName
= sizeof(szName
) / sizeof(WCHAR
);
195 FolderOptionsFileTypesDlg(
205 InitializeFileTypesListCtrl(hwndDlg
);
215 ShowFolderOptionsDialog(HWND hWnd
, HINSTANCE hInst
)
217 PROPSHEETHEADERW pinfo
;
218 HPROPSHEETPAGE hppages
[3];
219 HPROPSHEETPAGE hpage
;
221 WCHAR szOptions
[100];
223 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_GENERAL_DLG", FolderOptionsGeneralDlg
, 0, NULL
);
225 hppages
[num_pages
++] = hpage
;
227 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_VIEW_DLG", FolderOptionsViewDlg
, 0, NULL
);
229 hppages
[num_pages
++] = hpage
;
231 hpage
= SH_CreatePropertySheetPage("FOLDER_OPTIONS_FILETYPES_DLG", FolderOptionsFileTypesDlg
, 0, NULL
);
233 hppages
[num_pages
++] = hpage
;
235 szOptions
[0] = L
'\0';
236 LoadStringW(shell32_hInstance
, IDS_FOLDER_OPTIONS
, szOptions
, sizeof(szOptions
) / sizeof(WCHAR
));
237 szOptions
[(sizeof(szOptions
)/sizeof(WCHAR
))-1] = L
'\0';
239 memset(&pinfo
, 0x0, sizeof(PROPSHEETHEADERW
));
240 pinfo
.dwSize
= sizeof(PROPSHEETHEADERW
);
241 pinfo
.dwFlags
= PSH_NOCONTEXTHELP
;
242 pinfo
.nPages
= num_pages
;
243 pinfo
.u3
.phpage
= hppages
;
244 pinfo
.pszCaption
= szOptions
;
246 PropertySheetW(&pinfo
);
250 Options_RunDLLCommon(HWND hWnd
, HINSTANCE hInst
, int fOptions
, DWORD nCmdShow
)
255 ShowFolderOptionsDialog(hWnd
, hInst
);
258 // show taskbar options dialog
259 FIXME("notify explorer to show taskbar options dialog");
260 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
263 FIXME("unrecognized options id %d\n", fOptions
);
267 /*************************************************************************
268 * Options_RunDLL (SHELL32.@)
270 VOID WINAPI
Options_RunDLL(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
272 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
274 /*************************************************************************
275 * Options_RunDLLA (SHELL32.@)
277 VOID WINAPI
Options_RunDLLA(HWND hWnd
, HINSTANCE hInst
, LPCSTR cmd
, DWORD nCmdShow
)
279 Options_RunDLLCommon(hWnd
, hInst
, StrToIntA(cmd
), nCmdShow
);
282 /*************************************************************************
283 * Options_RunDLLW (SHELL32.@)
285 VOID WINAPI
Options_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
)
287 Options_RunDLLCommon(hWnd
, hInst
, StrToIntW(cmd
), nCmdShow
);
292 CountFolderAndFiles(LPVOID lParam
)
294 WIN32_FIND_DATAW FindData
;
299 PFOLDER_PROPERTIES_CONTEXT pContext
= (PFOLDER_PROPERTIES_CONTEXT
) lParam
;
301 pOffset
= PathAddBackslashW(pContext
->szFolderPath
);
305 Length
= pOffset
- pContext
->szFolderPath
;
307 wcscpy(pOffset
, L
"*.*");
308 hFile
= FindFirstFileW(pContext
->szFolderPath
, &FindData
);
309 if (hFile
== INVALID_HANDLE_VALUE
)
314 ret
= FindNextFileW(hFile
, &FindData
);
317 if (FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
319 if (FindData
.cFileName
[0] == L
'.' && FindData
.cFileName
[1] == L
'.' &&
320 FindData
.cFileName
[2] == L
'\0')
324 wcscpy(pOffset
, FindData
.cFileName
);
325 CountFolderAndFiles((LPVOID
)pContext
);
331 pContext
->bSize
.u
.LowPart
+= FindData
.nFileSizeLow
;
332 pContext
->bSize
.u
.HighPart
+= FindData
.nFileSizeHigh
;
335 else if (GetLastError() == ERROR_NO_MORE_FILES
)
347 InitializeFolderGeneralDlg(PFOLDER_PROPERTIES_CONTEXT pContext
)
350 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute
;
353 WCHAR szBuffer
[MAX_PATH
+5];
354 WCHAR szFormat
[30] = {0};
356 static const WCHAR wFormat
[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
358 pFolderName
= wcsrchr(pContext
->szFolderPath
, L
'\\');
362 /* set folder name */
363 SendDlgItemMessageW(pContext
->hwndDlg
, 14001, WM_SETTEXT
, 0, (LPARAM
) (pFolderName
+ 1));
364 /* set folder location */
365 pFolderName
[0] = L
'\0';
366 if (wcslen(pContext
->szFolderPath
) == 2)
368 /* folder is located at root */
369 WCHAR szDrive
[4] = {L
'C',L
':',L
'\\',L
'\0'};
370 szDrive
[0] = pContext
->szFolderPath
[0];
371 SendDlgItemMessageW(pContext
->hwndDlg
, 14007, WM_SETTEXT
, 0, (LPARAM
) szDrive
);
375 SendDlgItemMessageW(pContext
->hwndDlg
, 14007, WM_SETTEXT
, 0, (LPARAM
) pContext
->szFolderPath
);
377 pFolderName
[0] = L
'\\';
378 /* get folder properties */
379 if (GetFileAttributesExW(pContext
->szFolderPath
, GetFileExInfoStandard
, (LPVOID
)&FolderAttribute
))
381 if (FolderAttribute
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
383 /* check readonly button */
384 SendDlgItemMessage(pContext
->hwndDlg
, 14021, BM_SETCHECK
, BST_CHECKED
, 0);
387 if (FolderAttribute
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
389 /* check hidden button */
390 SendDlgItemMessage(pContext
->hwndDlg
, 14022, BM_SETCHECK
, BST_CHECKED
, 0);
393 if (FileTimeToLocalFileTime(&FolderAttribute
.ftCreationTime
, &ft
))
395 FileTimeToSystemTime(&ft
, &dt
);
396 sprintfW (szBuffer
, wFormat
, dt
.wDay
, dt
.wMonth
, dt
.wYear
, dt
.wHour
, dt
.wMinute
);
397 SendDlgItemMessageW(pContext
->hwndDlg
, 14015, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
400 /* now enumerate enumerate contents */
401 wcscpy(szBuffer
, pContext
->szFolderPath
);
402 CountFolderAndFiles((LPVOID
)pContext
);
403 wcscpy(pContext
->szFolderPath
, szBuffer
);
404 /* set folder details */
405 LoadStringW(shell32_hInstance
, IDS_FILE_FOLDER
, szFormat
, sizeof(szFormat
)/sizeof(WCHAR
));
406 szFormat
[(sizeof(szFormat
)/sizeof(WCHAR
))-1] = L
'\0';
407 sprintfW(szBuffer
, szFormat
, pContext
->cFiles
, pContext
->cFolder
);
408 SendDlgItemMessageW(pContext
->hwndDlg
, 14011, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
410 if (StrFormatByteSizeW(pContext
->bSize
.QuadPart
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
412 /* store folder size */
413 SendDlgItemMessageW(pContext
->hwndDlg
, 14009, WM_SETTEXT
, 0, (LPARAM
) szBuffer
);
420 FolderPropertiesGeneralDlg(
427 LPPROPSHEETPAGEW ppsp
;
428 PFOLDER_PROPERTIES_CONTEXT pContext
;
430 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute
;
438 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
441 hIcon
= LoadIconW(shell32_hInstance
, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPEN
));
443 SendDlgItemMessageW(hwndDlg
, 14000, STM_SETICON
, (WPARAM
)hIcon
, 0);
445 pContext
= SHAlloc(sizeof(FOLDER_PROPERTIES_CONTEXT
));
448 ZeroMemory(pContext
, sizeof(FOLDER_PROPERTIES_CONTEXT
));
449 pContext
->hwndDlg
= hwndDlg
;
450 wcscpy(pContext
->szFolderPath
, (LPWSTR
)ppsp
->lParam
);
451 SetWindowLongPtr(hwndDlg
, DWL_USER
, (LONG_PTR
)pContext
);
452 InitializeFolderGeneralDlg(pContext
);
456 if (HIWORD(wParam
) == BN_CLICKED
)
458 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
462 pContext
= (PFOLDER_PROPERTIES_CONTEXT
)GetWindowLong(hwndDlg
, DWL_USER
);
463 SHFree((LPVOID
)pContext
);
466 pContext
= (PFOLDER_PROPERTIES_CONTEXT
)GetWindowLong(hwndDlg
, DWL_USER
);
467 lppsn
= (LPPSHNOTIFY
) lParam
;
468 if (lppsn
->hdr
.code
== PSN_APPLY
)
470 if (GetFileAttributesExW(pContext
->szFolderPath
, GetFileExInfoStandard
, (LPVOID
)&FolderAttribute
))
472 res
= SendDlgItemMessageW(hwndDlg
, 14021, BM_GETCHECK
, 0, 0);
473 if (res
== BST_CHECKED
)
474 FolderAttribute
.dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
476 FolderAttribute
.dwFileAttributes
&= (~FILE_ATTRIBUTE_READONLY
);
478 res
= SendDlgItemMessageW(hwndDlg
, 14022, BM_GETCHECK
, 0, 0);
479 if (res
== BST_CHECKED
)
480 FolderAttribute
.dwFileAttributes
|= FILE_ATTRIBUTE_HIDDEN
;
482 FolderAttribute
.dwFileAttributes
&= (~FILE_ATTRIBUTE_HIDDEN
);
484 Attribute
= FolderAttribute
.dwFileAttributes
&
485 (FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_NORMAL
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
|FILE_ATTRIBUTE_TEMPORARY
);
487 SetFileAttributesW(pContext
->szFolderPath
, Attribute
);
489 SetWindowLong( hwndDlg
, DWL_MSGRESULT
, PSNRET_NOERROR
);
500 FolderAddPropSheetPageProc(HPROPSHEETPAGE hpage
, LPARAM lParam
)
502 PROPSHEETHEADERW
*ppsh
= (PROPSHEETHEADERW
*)lParam
;
503 if (ppsh
!= NULL
&& ppsh
->nPages
< MAX_PROPERTY_SHEET_PAGE
)
505 ppsh
->u3
.phpage
[ppsh
->nPages
++] = hpage
;
512 SH_ShowFolderProperties(LPWSTR pwszFolder
)
514 HPROPSHEETPAGE hppages
[MAX_PROPERTY_SHEET_PAGE
];
515 HPROPSHEETPAGE hpage
;
516 PROPSHEETHEADERW psh
;
518 WCHAR szName
[MAX_PATH
] = {0};
522 if (!PathIsDirectoryW(pwszFolder
))
525 pFolderName
= wcsrchr(pwszFolder
, L
'\\');
529 wcscpy(szName
, pFolderName
+ 1);
531 hpage
= SH_CreatePropertySheetPage("SHELL_FOLDER_GENERAL_DLG", FolderPropertiesGeneralDlg
, (LPARAM
)pwszFolder
, NULL
);
535 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
536 hppages
[psh
.nPages
] = hpage
;
538 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
539 psh
.dwFlags
= PSH_PROPTITLE
;
540 psh
.hwndParent
= NULL
;
541 psh
.u3
.phpage
= hppages
;
542 psh
.pszCaption
= szName
;
544 hpsx
= SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT
,
546 MAX_PROPERTY_SHEET_PAGE
-1);
548 SHAddFromPropSheetExtArray(hpsx
,
549 (LPFNADDPROPSHEETPAGE
)FolderAddPropSheetPageProc
,
552 ret
= PropertySheetW(&psh
);