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