diff options
Diffstat (limited to '')
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/shelutil.cpp | 210 |
1 files changed, 190 insertions, 20 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/shelutil.cpp b/src/libs/dutil/WixToolset.DUtil/shelutil.cpp index 2eb9a52a..72a0e5ce 100644 --- a/src/libs/dutil/WixToolset.DUtil/shelutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/shelutil.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #define ShelExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 9 | #define ShelExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
| 10 | #define ShelExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 10 | #define ShelExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
| 11 | #define ShelExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 11 | #define ShelExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
| 12 | #define ShelExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, e, s, __VA_ARGS__) | ||
| 12 | #define ShelExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 13 | #define ShelExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
| 13 | #define ShelExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_SHELUTIL, p, x, e, s, __VA_ARGS__) | 14 | #define ShelExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_SHELUTIL, p, x, e, s, __VA_ARGS__) |
| 14 | #define ShelExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, p, x, s, __VA_ARGS__) | 15 | #define ShelExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, p, x, s, __VA_ARGS__) |
| @@ -19,6 +20,10 @@ | |||
| 19 | 20 | ||
| 20 | static PFN_SHELLEXECUTEEXW vpfnShellExecuteExW = ::ShellExecuteExW; | 21 | static PFN_SHELLEXECUTEEXW vpfnShellExecuteExW = ::ShellExecuteExW; |
| 21 | 22 | ||
| 23 | static HRESULT DAPI GetFolderFromCsidl( | ||
| 24 | __out_z LPWSTR* psczFolderPath, | ||
| 25 | __in int csidlFolder | ||
| 26 | ); | ||
| 22 | static HRESULT GetDesktopShellView( | 27 | static HRESULT GetDesktopShellView( |
| 23 | __in REFIID riid, | 28 | __in REFIID riid, |
| 24 | __out void **ppv | 29 | __out void **ppv |
| @@ -57,7 +62,14 @@ extern "C" HRESULT DAPI ShelExec( | |||
| 57 | ) | 62 | ) |
| 58 | { | 63 | { |
| 59 | HRESULT hr = S_OK; | 64 | HRESULT hr = S_OK; |
| 60 | SHELLEXECUTEINFOW shExecInfo = {}; | 65 | SHELLEXECUTEINFOW shExecInfo = { }; |
| 66 | size_t cchWorkingDirectory = 0; | ||
| 67 | |||
| 68 | // CreateProcessW has undocumented MAX_PATH restriction for lpCurrentDirectory even when long path support is enabled. | ||
| 69 | if (wzWorkingDirectory && FAILED(::StringCchLengthW(wzWorkingDirectory, MAX_PATH - 1, &cchWorkingDirectory))) | ||
| 70 | { | ||
| 71 | wzWorkingDirectory = NULL; | ||
| 72 | } | ||
| 61 | 73 | ||
| 62 | shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); | 74 | shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); |
| 63 | shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; | 75 | shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; |
| @@ -159,11 +171,7 @@ LExit: | |||
| 159 | } | 171 | } |
| 160 | 172 | ||
| 161 | 173 | ||
| 162 | /******************************************************************** | 174 | static HRESULT DAPI GetFolderFromCsidl( |
| 163 | ShelGetFolder() - gets a folder by CSIDL. | ||
| 164 | |||
| 165 | *******************************************************************/ | ||
| 166 | extern "C" HRESULT DAPI ShelGetFolder( | ||
| 167 | __out_z LPWSTR* psczFolderPath, | 175 | __out_z LPWSTR* psczFolderPath, |
| 168 | __in int csidlFolder | 176 | __in int csidlFolder |
| 169 | ) | 177 | ) |
| @@ -185,19 +193,6 @@ LExit: | |||
| 185 | } | 193 | } |
| 186 | 194 | ||
| 187 | 195 | ||
| 188 | /******************************************************************** | ||
| 189 | ShelGetKnownFolder() - gets a folder by KNOWNFOLDERID. | ||
| 190 | |||
| 191 | Note: return E_NOTIMPL if called on pre-Vista operating systems. | ||
| 192 | *******************************************************************/ | ||
| 193 | #ifndef REFKNOWNFOLDERID | ||
| 194 | #define REFKNOWNFOLDERID REFGUID | ||
| 195 | #endif | ||
| 196 | |||
| 197 | #ifndef KF_FLAG_CREATE | ||
| 198 | #define KF_FLAG_CREATE 0x00008000 // Make sure that the folder already exists or create it and apply security specified in folder definition | ||
| 199 | #endif | ||
| 200 | |||
| 201 | EXTERN_C typedef HRESULT (STDAPICALLTYPE *PFN_SHGetKnownFolderPath)( | 196 | EXTERN_C typedef HRESULT (STDAPICALLTYPE *PFN_SHGetKnownFolderPath)( |
| 202 | REFKNOWNFOLDERID rfid, | 197 | REFKNOWNFOLDERID rfid, |
| 203 | DWORD dwFlags, | 198 | DWORD dwFlags, |
| @@ -249,6 +244,181 @@ LExit: | |||
| 249 | return hr; | 244 | return hr; |
| 250 | } | 245 | } |
| 251 | 246 | ||
| 247 | extern "C" HRESULT DAPI ShelGetFolder( | ||
| 248 | __out_z LPWSTR* psczFolderPath, | ||
| 249 | __in int csidlFolder | ||
| 250 | ) | ||
| 251 | { | ||
| 252 | HRESULT hr = S_OK; | ||
| 253 | LPWSTR sczPath = NULL; | ||
| 254 | KNOWNFOLDERID rfid = { }; | ||
| 255 | |||
| 256 | csidlFolder &= ~CSIDL_FLAG_MASK; | ||
| 257 | |||
| 258 | switch (csidlFolder) | ||
| 259 | { | ||
| 260 | case CSIDL_ADMINTOOLS: | ||
| 261 | rfid = FOLDERID_AdminTools; | ||
| 262 | break; | ||
| 263 | case CSIDL_APPDATA: | ||
| 264 | rfid = FOLDERID_RoamingAppData; | ||
| 265 | break; | ||
| 266 | case CSIDL_CDBURN_AREA: | ||
| 267 | rfid = FOLDERID_CDBurning; | ||
| 268 | break; | ||
| 269 | case CSIDL_COMMON_ADMINTOOLS: | ||
| 270 | rfid = FOLDERID_CommonAdminTools; | ||
| 271 | break; | ||
| 272 | case CSIDL_COMMON_APPDATA: | ||
| 273 | rfid = FOLDERID_ProgramData; | ||
| 274 | break; | ||
| 275 | case CSIDL_COMMON_DESKTOPDIRECTORY: | ||
| 276 | rfid = FOLDERID_PublicDesktop; | ||
| 277 | break; | ||
| 278 | case CSIDL_COMMON_DOCUMENTS: | ||
| 279 | rfid = FOLDERID_PublicDocuments; | ||
| 280 | break; | ||
| 281 | case CSIDL_COMMON_MUSIC: | ||
| 282 | rfid = FOLDERID_PublicMusic; | ||
| 283 | break; | ||
| 284 | case CSIDL_COMMON_OEM_LINKS: | ||
| 285 | rfid = FOLDERID_CommonOEMLinks; | ||
| 286 | break; | ||
| 287 | case CSIDL_COMMON_PICTURES: | ||
| 288 | rfid = FOLDERID_PublicPictures; | ||
| 289 | break; | ||
| 290 | case CSIDL_COMMON_PROGRAMS: | ||
| 291 | rfid = FOLDERID_CommonPrograms; | ||
| 292 | break; | ||
| 293 | case CSIDL_COMMON_STARTMENU: | ||
| 294 | rfid = FOLDERID_CommonStartMenu; | ||
| 295 | break; | ||
| 296 | case CSIDL_COMMON_STARTUP: __fallthrough; | ||
| 297 | case CSIDL_COMMON_ALTSTARTUP: | ||
| 298 | rfid = FOLDERID_CommonStartup; | ||
| 299 | break; | ||
| 300 | case CSIDL_COMMON_TEMPLATES: | ||
| 301 | rfid = FOLDERID_CommonTemplates; | ||
| 302 | break; | ||
| 303 | case CSIDL_COMMON_VIDEO: | ||
| 304 | rfid = FOLDERID_PublicVideos; | ||
| 305 | break; | ||
| 306 | case CSIDL_COOKIES: | ||
| 307 | rfid = FOLDERID_Cookies; | ||
| 308 | break; | ||
| 309 | case CSIDL_DESKTOP: | ||
| 310 | case CSIDL_DESKTOPDIRECTORY: | ||
| 311 | rfid = FOLDERID_Desktop; | ||
| 312 | break; | ||
| 313 | case CSIDL_FAVORITES: __fallthrough; | ||
| 314 | case CSIDL_COMMON_FAVORITES: | ||
| 315 | rfid = FOLDERID_Favorites; | ||
| 316 | break; | ||
| 317 | case CSIDL_FONTS: | ||
| 318 | rfid = FOLDERID_Fonts; | ||
| 319 | break; | ||
| 320 | case CSIDL_HISTORY: | ||
| 321 | rfid = FOLDERID_History; | ||
| 322 | break; | ||
| 323 | case CSIDL_INTERNET_CACHE: | ||
| 324 | rfid = FOLDERID_InternetCache; | ||
| 325 | break; | ||
| 326 | case CSIDL_LOCAL_APPDATA: | ||
| 327 | rfid = FOLDERID_LocalAppData; | ||
| 328 | break; | ||
| 329 | case CSIDL_MYMUSIC: | ||
| 330 | rfid = FOLDERID_Music; | ||
| 331 | break; | ||
| 332 | case CSIDL_MYPICTURES: | ||
| 333 | rfid = FOLDERID_Pictures; | ||
| 334 | break; | ||
| 335 | case CSIDL_MYVIDEO: | ||
| 336 | rfid = FOLDERID_Videos; | ||
| 337 | break; | ||
| 338 | case CSIDL_NETHOOD: | ||
| 339 | rfid = FOLDERID_NetHood; | ||
| 340 | break; | ||
| 341 | case CSIDL_PERSONAL: | ||
| 342 | rfid = FOLDERID_Documents; | ||
| 343 | break; | ||
| 344 | case CSIDL_PRINTHOOD: | ||
| 345 | rfid = FOLDERID_PrintHood; | ||
| 346 | break; | ||
| 347 | case CSIDL_PROFILE: | ||
| 348 | rfid = FOLDERID_Profile; | ||
| 349 | break; | ||
| 350 | case CSIDL_PROGRAM_FILES: | ||
| 351 | rfid = FOLDERID_ProgramFiles; | ||
| 352 | break; | ||
| 353 | case CSIDL_PROGRAM_FILESX86: | ||
| 354 | rfid = FOLDERID_ProgramFilesX86; | ||
| 355 | break; | ||
| 356 | case CSIDL_PROGRAM_FILES_COMMON: | ||
| 357 | rfid = FOLDERID_ProgramFilesCommon; | ||
| 358 | break; | ||
| 359 | case CSIDL_PROGRAM_FILES_COMMONX86: | ||
| 360 | rfid = FOLDERID_ProgramFilesCommonX86; | ||
| 361 | break; | ||
| 362 | case CSIDL_PROGRAMS: | ||
| 363 | rfid = FOLDERID_Programs; | ||
| 364 | break; | ||
| 365 | case CSIDL_RECENT: | ||
| 366 | rfid = FOLDERID_Recent; | ||
| 367 | break; | ||
| 368 | case CSIDL_RESOURCES: | ||
| 369 | rfid = FOLDERID_ResourceDir; | ||
| 370 | break; | ||
| 371 | case CSIDL_RESOURCES_LOCALIZED: | ||
| 372 | rfid = FOLDERID_LocalizedResourcesDir; | ||
| 373 | break; | ||
| 374 | case CSIDL_SENDTO: | ||
| 375 | rfid = FOLDERID_SendTo; | ||
| 376 | break; | ||
| 377 | case CSIDL_STARTMENU: | ||
| 378 | rfid = FOLDERID_StartMenu; | ||
| 379 | break; | ||
| 380 | case CSIDL_STARTUP: | ||
| 381 | case CSIDL_ALTSTARTUP: | ||
| 382 | rfid = FOLDERID_Startup; | ||
| 383 | break; | ||
| 384 | case CSIDL_SYSTEM: | ||
| 385 | rfid = FOLDERID_System; | ||
| 386 | break; | ||
| 387 | case CSIDL_SYSTEMX86: | ||
| 388 | rfid = FOLDERID_SystemX86; | ||
| 389 | break; | ||
| 390 | case CSIDL_TEMPLATES: | ||
| 391 | rfid = FOLDERID_Templates; | ||
| 392 | break; | ||
| 393 | case CSIDL_WINDOWS: | ||
| 394 | rfid = FOLDERID_Windows; | ||
| 395 | break; | ||
| 396 | default: | ||
| 397 | ShelExitWithRootFailure(hr, E_INVALIDARG, "Unknown csidl: %d", csidlFolder); | ||
| 398 | } | ||
| 399 | |||
| 400 | hr = ShelGetKnownFolder(&sczPath, rfid); | ||
| 401 | if (E_NOTIMPL == hr) | ||
| 402 | { | ||
| 403 | hr = S_FALSE; | ||
| 404 | } | ||
| 405 | ShelExitOnFailure(hr, "Failed to get known folder."); | ||
| 406 | |||
| 407 | if (S_FALSE == hr) | ||
| 408 | { | ||
| 409 | hr = GetFolderFromCsidl(&sczPath, csidlFolder); | ||
| 410 | ShelExitOnFailure(hr, "Failed to get csidl folder."); | ||
| 411 | } | ||
| 412 | |||
| 413 | *psczFolderPath = sczPath; | ||
| 414 | sczPath = NULL; | ||
| 415 | |||
| 416 | LExit: | ||
| 417 | ReleaseStr(sczPath); | ||
| 418 | |||
| 419 | return hr; | ||
| 420 | } | ||
| 421 | |||
| 252 | 422 | ||
| 253 | // Internal functions. | 423 | // Internal functions. |
| 254 | 424 | ||
| @@ -287,7 +457,7 @@ static HRESULT GetDesktopShellView( | |||
| 287 | else if (S_FALSE == hr) | 457 | else if (S_FALSE == hr) |
| 288 | { | 458 | { |
| 289 | //Windows XP | 459 | //Windows XP |
| 290 | hr = SHGetDesktopFolder(&psf); | 460 | hr = ::SHGetDesktopFolder(&psf); |
| 291 | ShelExitOnFailure(hr, "Failed to get desktop folder."); | 461 | ShelExitOnFailure(hr, "Failed to get desktop folder."); |
| 292 | 462 | ||
| 293 | hr = psf->CreateViewObject(NULL, IID_IShellView, ppv); | 463 | hr = psf->CreateViewObject(NULL, IID_IShellView, ppv); |
