[SHELL32] Deduplicate MAX_PROPERTY_SHEET_PAGE and AddPropSheetPageCallback(). #179
[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 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 /*************************************************************************
71 *
72 * SH_ShowPropertiesDialog
73 *
74 * called from ShellExecuteExW32
75 *
76 * pwszPath contains path of folder/file
77 *
78 * TODO: provide button change application type if file has registered type
79 * make filename field editable and apply changes to filename on close
80 */
81
82 BOOL
83 SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
84 {
85 HPSXA hpsxa[3] = {NULL, NULL, NULL};
86 CComObject<CFileDefExt> *pFileDefExt = NULL;
87
88 TRACE("SH_ShowPropertiesDialog entered filename %s\n", debugstr_w(pwszPath));
89
90 if (pwszPath == NULL || !wcslen(pwszPath))
91 return FALSE;
92
93 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
94 memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
95
96 /* Make a copy of path */
97 WCHAR wszPath[MAX_PATH];
98 StringCbCopyW(wszPath, sizeof(wszPath), pwszPath);
99
100 /* remove trailing \\ at the end of path */
101 PathRemoveBackslashW(wszPath);
102
103 /* Handle drives */
104 if (PathIsRootW(wszPath))
105 return SUCCEEDED(SH_ShowDriveProperties(wszPath, pidlFolder, apidl));
106
107 /* Handle files and folders */
108 PROPSHEETHEADERW Header;
109 memset(&Header, 0x0, sizeof(PROPSHEETHEADERW));
110 Header.dwSize = sizeof(PROPSHEETHEADERW);
111 Header.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
112 Header.phpage = hppages;
113 Header.pszCaption = PathFindFileNameW(wszPath);
114
115 CComPtr<IDataObject> pDataObj;
116 HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
117
118 if (SUCCEEDED(hr))
119 {
120 hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
121 if (SUCCEEDED(hr))
122 {
123 pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count
124 hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL);
125 if (SUCCEEDED(hr))
126 {
127 hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
128 if (FAILED(hr))
129 ERR("AddPages failed\n");
130 } else
131 ERR("Initialize failed\n");
132 }
133
134 LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
135 }
136
137 INT_PTR Result = PropertySheetW(&Header);
138
139 for (UINT i = 0; i < 3; ++i)
140 if (hpsxa[i])
141 SHDestroyPropSheetExtArray(hpsxa[i]);
142 if (pFileDefExt)
143 pFileDefExt->Release();
144
145 return (Result != -1);
146 }
147
148 /*EOF */