[SHELL32] Don't show error when closing disk prop sheet (#144)
[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 #define MAX_PROPERTY_SHEET_PAGE 32
26
27 WINE_DEFAULT_DEBUG_CHANNEL(shell);
28
29 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
30
31 static BOOL CALLBACK
32 AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
33 {
34 PROPSHEETHEADERW *pHeader = (PROPSHEETHEADERW *)lParam;
35
36 if (pHeader->nPages < MAX_PROPERTY_SHEET_PAGE)
37 {
38 pHeader->phpage[pHeader->nPages++] = hPage;
39 return TRUE;
40 }
41
42 return FALSE;
43 }
44
45 static UINT
46 LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPages, HPSXA *phpsxa, IDataObject *pDataObj)
47 {
48 WCHAR wszBuf[MAX_PATH];
49 UINT cPages = 0, i = 0;
50
51 LPWSTR pwszFilename = PathFindFileNameW(pwszPath);
52 BOOL bDir = PathIsDirectoryW(pwszPath);
53
54 if (bDir)
55 {
56 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Folder", cMaxPages - cPages, pDataObj);
57 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
58
59 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Directory", cMaxPages - cPages, pDataObj);
60 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
61 }
62 else
63 {
64 /* Load property sheet handlers from ext key */
65 LPWSTR pwszExt = PathFindExtensionW(pwszFilename);
66 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, pwszExt, cMaxPages - cPages, pDataObj);
67 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
68
69 /* Load property sheet handlers from prog id key */
70 DWORD cbBuf = sizeof(wszBuf);
71 if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &cbBuf) == ERROR_SUCCESS)
72 {
73 TRACE("EnumPropSheetExt wszBuf %s, pwszExt %s\n", debugstr_w(wszBuf), debugstr_w(pwszExt));
74 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszBuf, cMaxPages - cPages, pDataObj);
75 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
76 }
77
78 /* Add property sheet handlers from "*" key */
79 phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"*", cMaxPages - cPages, pDataObj);
80 cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
81 }
82
83 return cPages;
84 }
85
86 /*************************************************************************
87 *
88 * SH_ShowPropertiesDialog
89 *
90 * called from ShellExecuteExW32
91 *
92 * pwszPath contains path of folder/file
93 *
94 * TODO: provide button change application type if file has registered type
95 * make filename field editable and apply changes to filename on close
96 */
97
98 BOOL
99 SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
100 {
101 HPSXA hpsxa[3] = {NULL, NULL, NULL};
102 CComObject<CFileDefExt> *pFileDefExt = NULL;
103
104 TRACE("SH_ShowPropertiesDialog entered filename %s\n", debugstr_w(pwszPath));
105
106 if (pwszPath == NULL || !wcslen(pwszPath))
107 return FALSE;
108
109 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
110 memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
111
112 /* Make a copy of path */
113 WCHAR wszPath[MAX_PATH];
114 StringCbCopyW(wszPath, sizeof(wszPath), pwszPath);
115
116 /* remove trailing \\ at the end of path */
117 PathRemoveBackslashW(wszPath);
118
119 /* Handle drives */
120 if (PathIsRootW(wszPath))
121 return SUCCEEDED(SH_ShowDriveProperties(wszPath, pidlFolder, apidl));
122
123 /* Handle files and folders */
124 PROPSHEETHEADERW Header;
125 memset(&Header, 0x0, sizeof(PROPSHEETHEADERW));
126 Header.dwSize = sizeof(PROPSHEETHEADERW);
127 Header.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
128 Header.phpage = hppages;
129 Header.pszCaption = PathFindFileNameW(wszPath);
130
131 CComPtr<IDataObject> pDataObj;
132 HRESULT hr = SHCreateDataObject(pidlFolder, 1, apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
133
134 if (SUCCEEDED(hr))
135 {
136 hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
137 if (SUCCEEDED(hr))
138 {
139 pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count
140 hr = pFileDefExt->Initialize(pidlFolder, pDataObj, NULL);
141 if (SUCCEEDED(hr))
142 {
143 hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
144 if (FAILED(hr))
145 ERR("AddPages failed\n");
146 } else
147 ERR("Initialize failed\n");
148 }
149
150 LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
151 }
152
153 INT_PTR Result = PropertySheetW(&Header);
154
155 for (UINT i = 0; i < 3; ++i)
156 if (hpsxa[i])
157 SHDestroyPropSheetExtArray(hpsxa[i]);
158 if (pFileDefExt)
159 pFileDefExt->Release();
160
161 return (Result != -1);
162 }
163
164 /*EOF */