9433883cfd9878bfee781acf35bd67a405a14749
[reactos.git] / dll / win32 / shell32 / dialogs / fprop.cpp
1 /*
2 * Shell Library Functions
3 *
4 * Copyright 2005 Johannes Anderwald
5 * Copyright 2012 Rafal Harabien
6 * Copyright 2017-2018 Katayama Hirofumi MZ
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "precomp.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(shell);
26
27 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
28
29 static UINT
30 LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPages, HPSXA *phpsxa, IDataObject *pDataObj)
31 {
32 WCHAR wszBuf[MAX_PATH];
33 UINT cPages = 0, i = 0;
34
35 LPWSTR pwszFilename = PathFindFileNameW(pwszPath);
36 BOOL bDir = PathIsDirectoryW(pwszPath);
37
38 if (bDir)
39 {
40 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Folder", cMaxPages - cPages, pDataObj);
41 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
42
43 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Directory", cMaxPages - cPages, pDataObj);
44 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
45 }
46 else
47 {
48 /* Load property sheet handlers from ext key */
49 LPWSTR pwszExt = PathFindExtensionW(pwszFilename);
50 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, pwszExt, cMaxPages - cPages, pDataObj);
51 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
52
53 /* Load property sheet handlers from prog id key */
54 DWORD cbBuf = sizeof(wszBuf);
55 if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &cbBuf) == ERROR_SUCCESS)
56 {
57 TRACE("EnumPropSheetExt wszBuf %s, pwszExt %s\n", debugstr_w(wszBuf), debugstr_w(pwszExt));
58 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszBuf, cMaxPages - cPages, pDataObj);
59 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
60 }
61
62 /* Add property sheet handlers from "*" key */
63 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"*", cMaxPages - cPages, pDataObj);
64 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
65 }
66
67 return cPages;
68 }
69
70 // CStubWindow32 --- The owner window of file property sheets.
71 // This window hides taskbar button of property sheet.
72 class CStubWindow32 : public CWindowImpl<CStubWindow32>
73 {
74 public:
75 DECLARE_WND_CLASS_EX(_T("StubWindow32"), 0, COLOR_WINDOWTEXT)
76
77 BEGIN_MSG_MAP(CPaletteWindow)
78 END_MSG_MAP()
79 };
80
81 /*************************************************************************
82 *
83 * SH_ShowPropertiesDialog
84 *
85 * called from ShellExecuteExW32
86 *
87 * pwszPath contains path of folder/file
88 *
89 * TODO: provide button change application type if file has registered type
90 * make filename field editable and apply changes to filename on close
91 */
92
93 BOOL
94 SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
95 {
96 HPSXA hpsxa[3] = {NULL, NULL, NULL};
97 CComObject<CFileDefExt> *pFileDefExt = NULL;
98
99 TRACE("SH_ShowPropertiesDialog entered filename %s\n", debugstr_w(pwszPath));
100
101 if (pwszPath == NULL || !wcslen(pwszPath))
102 return FALSE;
103
104 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
105 memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
106
107 /* Make a copy of path */
108 WCHAR wszPath[MAX_PATH];
109 StringCbCopyW(wszPath, sizeof(wszPath), pwszPath);
110
111 /* remove trailing \\ at the end of path */
112 PathRemoveBackslashW(wszPath);
113
114 /* Handle drives */
115 if (PathIsRootW(wszPath))
116 return SUCCEEDED(SH_ShowDriveProperties(wszPath, pidlFolder, apidl));
117
118 DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
119 DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
120 CStubWindow32 stub;
121 if (!stub.Create(NULL, NULL, NULL, style, exstyle))
122 return E_FAIL;
123
124 /* Handle files and folders */
125 PROPSHEETHEADERW Header;
126 memset(&Header, 0x0, sizeof(PROPSHEETHEADERW));
127 Header.dwSize = sizeof(PROPSHEETHEADERW);
128 Header.hwndParent = stub;
129 Header.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
130 Header.phpage = hppages;
131 Header.pszCaption = PathFindFileNameW(wszPath);
132
133 CComPtr<IDataObject> pDataObj;
134 HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
135
136 if (SUCCEEDED(hr))
137 {
138 hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
139 if (SUCCEEDED(hr))
140 {
141 pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count
142 hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL);
143 if (SUCCEEDED(hr))
144 {
145 hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
146 if (FAILED(hr))
147 ERR("AddPages failed\n");
148 } else
149 ERR("Initialize failed\n");
150 }
151
152 LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
153 }
154
155 INT_PTR Result = PropertySheetW(&Header);
156
157 for (UINT i = 0; i < 3; ++i)
158 if (hpsxa[i])
159 SHDestroyPropSheetExtArray(hpsxa[i]);
160 if (pFileDefExt)
161 pFileDefExt->Release();
162
163 stub.DestroyWindow();
164
165 return (Result != -1);
166 }
167
168 /*EOF */