aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-08-10 19:24:24 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-08-10 20:27:48 -0500
commit3756ae7c8dc60d459511d0b067ebef5efb052746 (patch)
tree5aa0505d3ab4e4337575597bcad9c6fd641ea78d
parent84e7b6d277e5c3d118e11a45834d420254a758c0 (diff)
downloadwix-3756ae7c8dc60d459511d0b067ebef5efb052746.tar.gz
wix-3756ae7c8dc60d459511d0b067ebef5efb052746.tar.bz2
wix-3756ae7c8dc60d459511d0b067ebef5efb052746.zip
Use IFileOpenDialog instead of SHBrowseForFolder and GetOpenFileName.
It is the recommended option since Vista and has better long path support.
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp26
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/wndutil.h27
-rw-r--r--src/libs/dutil/WixToolset.DUtil/thmutil.cpp67
-rw-r--r--src/libs/dutil/WixToolset.DUtil/wndutil.cpp157
-rw-r--r--src/tools/thmviewer/thmviewer.cpp27
5 files changed, 234 insertions, 70 deletions
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index d7b5a269..8544ff0e 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -1145,26 +1145,19 @@ public: // IBootstrapperApplication
1145 ) 1145 )
1146 { 1146 {
1147 HRESULT hr = S_OK; 1147 HRESULT hr = S_OK;
1148 LPWSTR sczPath = NULL;
1148 1149
1149 if (BOOTSTRAPPER_CACHE_RESOLVE_NONE == *pAction && BOOTSTRAPPER_DISPLAY_FULL == m_command.display) // prompt to change the source location. 1150 if (BOOTSTRAPPER_CACHE_RESOLVE_NONE == *pAction && BOOTSTRAPPER_DISPLAY_FULL == m_command.display) // prompt to change the source location.
1150 { 1151 {
1151 OPENFILENAMEW ofn = { }; 1152 static COMDLG_FILTERSPEC vrgFilters[] =
1152 WCHAR wzFile[MAX_PATH] = { }; 1153 {
1153 1154 { L"All Files", L"*.*" },
1154 ::StringCchCopyW(wzFile, countof(wzFile), rgSearchPaths[dwRecommendedSearchPath]); 1155 };
1155
1156 ofn.lStructSize = sizeof(ofn);
1157 ofn.hwndOwner = m_hWnd;
1158 ofn.lpstrFile = wzFile;
1159 ofn.nMaxFile = countof(wzFile);
1160 ofn.lpstrFilter = L"All Files\0*.*\0";
1161 ofn.nFilterIndex = 1;
1162 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
1163 ofn.lpstrTitle = m_pTheme->sczCaption;
1164 1156
1165 if (::GetOpenFileNameW(&ofn)) 1157 hr = WnduShowOpenFileDialog(m_hWnd, TRUE, TRUE, m_pTheme->sczCaption, vrgFilters, countof(vrgFilters), 1, rgSearchPaths[dwRecommendedSearchPath], &sczPath);
1158 if (SUCCEEDED(hr))
1166 { 1159 {
1167 hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); 1160 hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, sczPath);
1168 *pAction = BOOTSTRAPPER_CACHE_RESOLVE_RETRY; 1161 *pAction = BOOTSTRAPPER_CACHE_RESOLVE_RETRY;
1169 } 1162 }
1170 else 1163 else
@@ -1175,6 +1168,9 @@ public: // IBootstrapperApplication
1175 // else there's nothing more we can do in non-interactive mode 1168 // else there's nothing more we can do in non-interactive mode
1176 1169
1177 *pfCancel |= CheckCanceled(); 1170 *pfCancel |= CheckCanceled();
1171
1172 ReleaseStr(sczPath);
1173
1178 return hr; 1174 return hr;
1179 } 1175 }
1180 1176
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/wndutil.h b/src/libs/dutil/WixToolset.DUtil/inc/wndutil.h
index 8de77f6e..ad4e07b0 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/wndutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/wndutil.h
@@ -35,6 +35,33 @@ HRESULT DAPI WnduGetControlText(
35 __inout_z LPWSTR* psczText 35 __inout_z LPWSTR* psczText
36 ); 36 );
37 37
38/********************************************************************
39 WnduShowOpenFileDialog - shows the system dialog to select a file for opening.
40
41*******************************************************************/
42HRESULT DAPI WnduShowOpenFileDialog(
43 __in_opt HWND hwndParent,
44 __in BOOL fForcePathExists,
45 __in BOOL fForceFileExists,
46 __in_opt LPCWSTR wzTitle,
47 __in_opt COMDLG_FILTERSPEC* rgFilters,
48 __in DWORD cFilters,
49 __in DWORD dwDefaultFilter,
50 __in_opt LPCWSTR wzDefaultPath,
51 __inout LPWSTR* psczPath
52 );
53
54/********************************************************************
55 WnduShowOpenFolderDialog - shows the system dialog to select a folder.
56
57*******************************************************************/
58HRESULT DAPI WnduShowOpenFolderDialog(
59 __in_opt HWND hwndParent,
60 __in BOOL fForceFileSystem,
61 __in_opt LPCWSTR wzTitle,
62 __inout LPWSTR* psczPath
63 );
64
38#ifdef __cplusplus 65#ifdef __cplusplus
39} 66}
40#endif 67#endif
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
index 52a52a1e..f7f7c5b6 100644
--- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
@@ -4992,54 +4992,47 @@ static void OnBrowseDirectory(
4992 ) 4992 )
4993{ 4993{
4994 HRESULT hr = S_OK; 4994 HRESULT hr = S_OK;
4995 WCHAR wzPath[MAX_PATH] = { }; 4995 LPWSTR sczPath = NULL;
4996 BROWSEINFOW browseInfo = { }; 4996 THEME_CONTROL* pTargetControl = NULL;
4997 PIDLIST_ABSOLUTE pidl = NULL; 4997 BOOL fSetVariable = NULL != pTheme->pfnSetStringVariable;
4998 4998
4999 browseInfo.hwndOwner = pTheme->hwndParent; 4999 hr = WnduShowOpenFolderDialog(pTheme->hwndParent, TRUE, pTheme->sczCaption, &sczPath);
5000 browseInfo.pszDisplayName = wzPath; 5000 if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
5001 browseInfo.lpszTitle = pTheme->sczCaption;
5002 browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
5003 pidl = ::SHBrowseForFolderW(&browseInfo);
5004 if (pidl && ::SHGetPathFromIDListW(pidl, wzPath))
5005 { 5001 {
5006 // Since editbox changes aren't immediately saved off, we have to treat them differently. 5002 ExitFunction();
5007 THEME_CONTROL* pTargetControl = NULL; 5003 }
5008 BOOL fSetVariable = NULL != pTheme->pfnSetStringVariable; 5004 ThmExitOnFailure(hr, "Failed to prompt user for directory.");
5009
5010 for (DWORD i = 0; i < pTheme->cControls; ++i)
5011 {
5012 THEME_CONTROL* pControl = pTheme->rgControls + i;
5013
5014 if ((!pControl->wPageId || pControl->wPageId == pTheme->dwCurrentPageId) &&
5015 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pControl->sczName, -1, pAction->BrowseDirectory.sczVariableName, -1))
5016 {
5017 pTargetControl = pControl;
5018 break;
5019 }
5020 }
5021 5005
5022 if (pTargetControl && !pTargetControl->fDisableAutomaticFunctionality && (!fSetVariable || THEME_CONTROL_TYPE_EDITBOX == pTargetControl->type)) 5006 for (DWORD i = 0; i < pTheme->cControls; ++i)
5023 { 5007 {
5024 fSetVariable = FALSE; 5008 THEME_CONTROL* pControl = pTheme->rgControls + i;
5025 hr = ThemeSetTextControl(pTargetControl, wzPath);
5026 ThmExitOnFailure(hr, "Failed to set text on control: %ls", pTargetControl->sczName);
5027 }
5028 5009
5029 if (fSetVariable) 5010 if ((!pControl->wPageId || pControl->wPageId == pTheme->dwCurrentPageId) &&
5011 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pControl->sczName, -1, pAction->BrowseDirectory.sczVariableName, -1))
5030 { 5012 {
5031 hr = pTheme->pfnSetStringVariable(pAction->BrowseDirectory.sczVariableName, wzPath, FALSE, pTheme->pvVariableContext); 5013 pTargetControl = pControl;
5032 ThmExitOnFailure(hr, "Failed to set variable: %ls", pAction->BrowseDirectory.sczVariableName); 5014 break;
5033 } 5015 }
5016 }
5034 5017
5035 ThemeShowPageEx(pTheme, pTheme->dwCurrentPageId, SW_SHOW, THEME_SHOW_PAGE_REASON_REFRESH); 5018 // Since editbox changes aren't immediately saved off, we have to treat them differently.
5019 if (pTargetControl && !pTargetControl->fDisableAutomaticFunctionality && (!fSetVariable || THEME_CONTROL_TYPE_EDITBOX == pTargetControl->type))
5020 {
5021 fSetVariable = FALSE;
5022 hr = ThemeSetTextControl(pTargetControl, sczPath);
5023 ThmExitOnFailure(hr, "Failed to set text on control: %ls", pTargetControl->sczName);
5036 } 5024 }
5037 5025
5038LExit: 5026 if (fSetVariable)
5039 if (pidl)
5040 { 5027 {
5041 ::CoTaskMemFree(pidl); 5028 hr = pTheme->pfnSetStringVariable(pAction->BrowseDirectory.sczVariableName, sczPath, FALSE, pTheme->pvVariableContext);
5029 ThmExitOnFailure(hr, "Failed to set variable: %ls", pAction->BrowseDirectory.sczVariableName);
5042 } 5030 }
5031
5032 ThemeShowPageEx(pTheme, pTheme->dwCurrentPageId, SW_SHOW, THEME_SHOW_PAGE_REASON_REFRESH);
5033
5034LExit:
5035 ReleaseStr(sczPath);
5043} 5036}
5044 5037
5045static BOOL OnButtonClicked( 5038static BOOL OnButtonClicked(
diff --git a/src/libs/dutil/WixToolset.DUtil/wndutil.cpp b/src/libs/dutil/WixToolset.DUtil/wndutil.cpp
index b75b0491..5d832e50 100644
--- a/src/libs/dutil/WixToolset.DUtil/wndutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/wndutil.cpp
@@ -161,6 +161,163 @@ LExit:
161} 161}
162 162
163 163
164DAPI_(HRESULT) WnduShowOpenFileDialog(
165 __in_opt HWND hwndParent,
166 __in BOOL fForcePathExists,
167 __in BOOL fForceFileExists,
168 __in_opt LPCWSTR wzTitle,
169 __in COMDLG_FILTERSPEC* rgFilters,
170 __in DWORD cFilters,
171 __in DWORD dwDefaultFilter,
172 __in_opt LPCWSTR wzDefaultPath,
173 __inout LPWSTR* psczPath
174 )
175{
176 HRESULT hr = S_OK;
177 IFileOpenDialog* pFileOpenDialog = NULL;
178 FILEOPENDIALOGOPTIONS fos = 0;
179 FILEOPENDIALOGOPTIONS additionalFlags = FOS_NOCHANGEDIR;
180 IShellItem* psi = NULL;
181 LPWSTR sczDefaultDirectory = NULL;
182 LPWSTR sczPath = NULL;
183
184 hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpenDialog));
185 WnduExitOnFailure(hr, "Failed to create FileOpenDialog object.");
186
187 hr = pFileOpenDialog->SetTitle(wzTitle);
188 WnduExitOnFailure(hr, "Failed to set FileOpenDialog title.");
189
190 hr = pFileOpenDialog->GetOptions(&fos);
191 WnduExitOnFailure(hr, "Failed to get FileOpenDialog options.");
192
193 if (fForcePathExists)
194 {
195 additionalFlags |= FOS_PATHMUSTEXIST;
196 }
197
198 if (fForceFileExists)
199 {
200 additionalFlags |= FOS_FILEMUSTEXIST;
201 }
202
203 hr = pFileOpenDialog->SetOptions(fos | additionalFlags);
204 WnduExitOnFailure(hr, "Failed to set FileOpenDialog options.");
205
206 hr = pFileOpenDialog->SetFileTypes(cFilters, rgFilters);
207 WnduExitOnFailure(hr, "Failed to set FileOpenDialog file types.");
208
209 hr = pFileOpenDialog->SetFileTypeIndex(dwDefaultFilter);
210 WnduExitOnFailure(hr, "Failed to set FileOpenDialog default file type.");
211
212 if (wzDefaultPath && *wzDefaultPath)
213 {
214 hr = PathGetDirectory(wzDefaultPath, &sczDefaultDirectory);
215 if (SUCCEEDED(hr))
216 {
217 hr = ::SHCreateItemFromParsingName(sczDefaultDirectory, NULL, IID_PPV_ARGS(&psi));
218 if (SUCCEEDED(hr))
219 {
220 hr = pFileOpenDialog->SetFolder(psi);
221 WnduExitOnFailure(hr, "Failed to set FileOpenDialog folder.");
222 }
223
224 ReleaseNullObject(psi);
225 }
226
227 hr = pFileOpenDialog->SetFileName(wzDefaultPath);
228 WnduExitOnFailure(hr, "Failed to set FileOpenDialog file name.");
229 }
230
231 hr = pFileOpenDialog->Show(hwndParent);
232 if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
233 {
234 ExitFunction();
235 }
236 WnduExitOnFailure(hr, "Failed to show FileOpenDialog for file.");
237
238 hr = pFileOpenDialog->GetResult(&psi);
239 WnduExitOnFailure(hr, "Failed to get FileOpenDialog result.");
240
241 hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &sczPath);
242 WnduExitOnFailure(hr, "Failed to get FileOpenDialog result path.");
243
244 hr = StrAllocString(psczPath, sczPath, 0);
245 WnduExitOnFailure(hr, "Failed to copy FileOpenDialog result path.");
246
247LExit:
248 if (sczPath)
249 {
250 ::CoTaskMemFree(sczPath);
251 }
252
253 ReleaseStr(sczDefaultDirectory);
254 ReleaseObject(psi);
255 ReleaseObject(pFileOpenDialog);
256
257 return hr;
258}
259
260
261DAPI_(HRESULT) WnduShowOpenFolderDialog(
262 __in_opt HWND hwndParent,
263 __in BOOL fForceFileSystem,
264 __in_opt LPCWSTR wzTitle,
265 __inout LPWSTR* psczPath
266 )
267{
268 HRESULT hr = S_OK;
269 IFileOpenDialog* pFileOpenDialog = NULL;
270 FILEOPENDIALOGOPTIONS fos = 0;
271 FILEOPENDIALOGOPTIONS additionalFlags = FOS_PICKFOLDERS | FOS_NOCHANGEDIR;
272 IShellItem* psi = NULL;
273 LPWSTR sczPath = NULL;
274
275 hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpenDialog));
276 WnduExitOnFailure(hr, "Failed to create FileOpenDialog object.");
277
278 hr = pFileOpenDialog->SetTitle(wzTitle);
279 WnduExitOnFailure(hr, "Failed to set FileOpenDialog title.");
280
281 hr = pFileOpenDialog->GetOptions(&fos);
282 WnduExitOnFailure(hr, "Failed to get FileOpenDialog options.");
283
284 if (fForceFileSystem)
285 {
286 additionalFlags |= FOS_FORCEFILESYSTEM;
287 }
288
289 hr = pFileOpenDialog->SetOptions(fos | additionalFlags);
290 WnduExitOnFailure(hr, "Failed to set FileOpenDialog options.");
291
292 hr = pFileOpenDialog->Show(hwndParent);
293 if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
294 {
295 ExitFunction();
296 }
297 WnduExitOnFailure(hr, "Failed to show FileOpenDialog for folder.");
298
299 hr = pFileOpenDialog->GetResult(&psi);
300 WnduExitOnFailure(hr, "Failed to get FileOpenDialog result.");
301
302 hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &sczPath);
303 WnduExitOnFailure(hr, "Failed to get FileOpenDialog result path.");
304
305 hr = StrAllocString(psczPath, sczPath, 0);
306 WnduExitOnFailure(hr, "Failed to copy FileOpenDialog result path.");
307
308LExit:
309 if (sczPath)
310 {
311 ::CoTaskMemFree(sczPath);
312 }
313
314 ReleaseObject(psi);
315 ReleaseObject(pFileOpenDialog);
316
317 return hr;
318}
319
320
164static DWORD CALLBACK RichEditStreamFromFileHandleCallback( 321static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
165 __in DWORD_PTR dwCookie, 322 __in DWORD_PTR dwCookie,
166 __in_bcount(cb) LPBYTE pbBuff, 323 __in_bcount(cb) LPBYTE pbBuff,
diff --git a/src/tools/thmviewer/thmviewer.cpp b/src/tools/thmviewer/thmviewer.cpp
index 38f3c4dc..4230dd35 100644
--- a/src/tools/thmviewer/thmviewer.cpp
+++ b/src/tools/thmviewer/thmviewer.cpp
@@ -66,6 +66,13 @@ static void CALLBACK ThmviewerTraceError(
66 __in va_list args 66 __in va_list args
67 ); 67 );
68 68
69static COMDLG_FILTERSPEC vrgFilters[] =
70{
71 { L"Theme Files (*.thm)", L"*.thm" },
72 { L"XML Files (*.xml)", L"*.xml" },
73 { L"All Files (*.*)", L"*.*" },
74};
75
69 76
70int WINAPI wWinMain( 77int WINAPI wWinMain(
71 __in HINSTANCE hInstance, 78 __in HINSTANCE hInstance,
@@ -110,24 +117,8 @@ int WINAPI wWinMain(
110 if (!sczThemeFile) 117 if (!sczThemeFile)
111 { 118 {
112 // Prompt for a path to the theme file. 119 // Prompt for a path to the theme file.
113 OPENFILENAMEW ofn = { }; 120 hr = WnduShowOpenFileDialog(hWnd, TRUE, TRUE, vpTheme->sczCaption, vrgFilters, countof(vrgFilters), 1, NULL, &sczThemeFile);
114 WCHAR wzFile[MAX_PATH] = { }; 121 if (FAILED(hr))
115
116 ofn.lStructSize = sizeof(ofn);
117 ofn.hwndOwner = hWnd;
118 ofn.lpstrFile = wzFile;
119 ofn.nMaxFile = countof(wzFile);
120 ofn.lpstrFilter = L"Theme Files (*.thm)\0*.thm\0XML Files (*.xml)\0*.xml\0All Files (*.*)\0*.*\0";
121 ofn.nFilterIndex = 1;
122 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
123 ofn.lpstrTitle = vpTheme->sczCaption;
124
125 if (::GetOpenFileNameW(&ofn))
126 {
127 hr = StrAllocString(&sczThemeFile, wzFile, 0);
128 ExitOnFailure(hr, "Failed to copy opened file to theme file.");
129 }
130 else
131 { 122 {
132 ::MessageBoxW(hWnd, L"Must specify a path to theme file.", vpTheme->sczCaption, MB_OK | MB_ICONERROR); 123 ::MessageBoxW(hWnd, L"Must specify a path to theme file.", vpTheme->sczCaption, MB_OK | MB_ICONERROR);
133 ExitFunction1(hr = E_INVALIDARG); 124 ExitFunction1(hr = E_INVALIDARG);