From ad71723cdf674478746e87886d99d9ef4b465bd6 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Sat, 26 Jan 2019 06:26:35 -0500 Subject: [PATCH] Factor WinRT GetFolderPath into static accessible via reflection (dotnet/coreclr#34873) Signed-off-by: dotnet-bot Commit migrated from https://github.com/dotnet/coreclr/commit/0657f407a95d78fcfa643a74d68a6562e8f67ba9 --- .../src/System/Environment.WinRT.cs | 129 +----------------- .../src/System/WinRTFolderPaths.cs | 144 +++++++++++++++++++++ 2 files changed, 146 insertions(+), 127 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/WinRTFolderPaths.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.WinRT.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.WinRT.cs index c757bea..72d66c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.WinRT.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.WinRT.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Windows.Foundation.Metadata; -using Windows.Storage; using System.IO; namespace System @@ -12,130 +10,7 @@ namespace System { public static string UserName => "Windows User"; public static string UserDomainName => "Windows Domain"; - - private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option) - { - // For testing we'll fall back if the needed APIs aren't present. - // - // We're not honoring the special folder options (noverify/create) for a few reasons. One, most of the - // folders always exist (e.g. it is moot). Two, most locations are inaccessible from an appcontainer - // currently - making it impossible to answer the question of existence or create if necessary. Thirdly, - // the Win32 API would create these folders with very specific ACLs, which even in the cases we can create - // are a significant compat risk (trying to replicate internal Windows behavior- it is documented that they - // set specific ACLs, but not which ones). - if (ApiInformation.IsTypePresent("Windows.Storage.UserDataPaths")) - { - return GetFolderPathCoreCurrent(folder); - } - else - { - return GetFolderPathCoreFallBack(folder); - } - } - - private static string GetFolderPathCoreCurrent(SpecialFolder folder) - { - // While all of these give back real paths, most of them are not accessible - // from an appcontainer currently (they will give access denied) - switch (folder) - { - case SpecialFolder.ApplicationData: - return UserDataPaths.GetDefault().RoamingAppData; - case SpecialFolder.CommonApplicationData: - return AppDataPaths.GetDefault().ProgramData; - case SpecialFolder.LocalApplicationData: - return AppDataPaths.GetDefault().LocalAppData; - case SpecialFolder.Cookies: - return AppDataPaths.GetDefault().Cookies; - case SpecialFolder.Desktop: - return AppDataPaths.GetDefault().Desktop; - case SpecialFolder.Favorites: - return AppDataPaths.GetDefault().Favorites; - case SpecialFolder.History: - return AppDataPaths.GetDefault().History; - case SpecialFolder.InternetCache: - return AppDataPaths.GetDefault().InternetCache; - case SpecialFolder.MyMusic: - return UserDataPaths.GetDefault().Music; - case SpecialFolder.MyPictures: - return UserDataPaths.GetDefault().Pictures; - case SpecialFolder.MyVideos: - return UserDataPaths.GetDefault().Videos; - case SpecialFolder.Recent: - return UserDataPaths.GetDefault().Recent; - case SpecialFolder.System: - return SystemDataPaths.GetDefault().System; - case SpecialFolder.Templates: - return UserDataPaths.GetDefault().Templates; - case SpecialFolder.DesktopDirectory: - return UserDataPaths.GetDefault().Desktop; - case SpecialFolder.Personal: - return UserDataPaths.GetDefault().Documents; - case SpecialFolder.CommonDocuments: - return SystemDataPaths.GetDefault().PublicDocuments; - case SpecialFolder.CommonMusic: - return SystemDataPaths.GetDefault().PublicMusic; - case SpecialFolder.CommonPictures: - return SystemDataPaths.GetDefault().PublicPictures; - case SpecialFolder.CommonDesktopDirectory: - return SystemDataPaths.GetDefault().PublicDesktop; - case SpecialFolder.CommonVideos: - return SystemDataPaths.GetDefault().PublicVideos; - case SpecialFolder.UserProfile: - return UserDataPaths.GetDefault().Profile; - case SpecialFolder.SystemX86: - return SystemDataPaths.GetDefault().SystemX86; - case SpecialFolder.Windows: - return SystemDataPaths.GetDefault().Windows; - - // The following aren't available on WinRT. Our default behavior - // is string.Empty for paths that aren't available. - // - // case SpecialFolder.Programs: - // case SpecialFolder.MyComputer: - // case SpecialFolder.SendTo: - // case SpecialFolder.StartMenu: - // case SpecialFolder.Startup: - // case SpecialFolder.ProgramFiles: - // case SpecialFolder.CommonProgramFiles: - // case SpecialFolder.AdminTools: - // case SpecialFolder.CDBurning: - // case SpecialFolder.CommonAdminTools: - // case SpecialFolder.CommonOemLinks: - // case SpecialFolder.CommonStartMenu: - // case SpecialFolder.CommonPrograms: - // case SpecialFolder.CommonStartup: - // case SpecialFolder.CommonTemplates: - // case SpecialFolder.Fonts: - // case SpecialFolder.NetworkShortcuts: - // case SpecialFolder.PrinterShortcuts: - // case SpecialFolder.CommonProgramFilesX86: - // case SpecialFolder.ProgramFilesX86: - // case SpecialFolder.Resources: - // case SpecialFolder.LocalizedResources: - - default: - return string.Empty; - } - } - - private static string GetFolderPathCoreFallBack(SpecialFolder folder) - { - // For testing without the new WinRT APIs. We cannot use Win32 APIs for - // special folders as they are not in the WACK. - switch (folder) - { - case SpecialFolder.ApplicationData: - return ApplicationData.Current.RoamingFolder?.Path; - case SpecialFolder.LocalApplicationData: - return ApplicationData.Current.LocalFolder?.Path; - case SpecialFolder.System: - return SystemDirectory; - case SpecialFolder.Windows: - return Path.GetDirectoryName(SystemDirectory); - default: - return string.Empty; - } - } + private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option) => + WinRTFolderPaths.GetFolderPath(folder, option); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/WinRTFolderPaths.cs b/src/libraries/System.Private.CoreLib/src/System/WinRTFolderPaths.cs new file mode 100644 index 0000000..020898a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/WinRTFolderPaths.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if SYSTEM_RUNTIME_WINDOWSRUNTIME_ASSEMBLY +extern alias System_Runtime_Extensions; +using static System_Runtime_Extensions::System.Environment; +#else +using static System.Environment; +#endif +using Windows.Foundation.Metadata; +using Windows.Storage; +using System.IO; + +namespace System +{ + internal static class WinRTFolderPaths + { + public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option) + { + // For testing we'll fall back if the needed APIs aren't present. + // + // We're not honoring the special folder options (noverify/create) for a few reasons. One, most of the + // folders always exist (e.g. it is moot). Two, most locations are inaccessible from an appcontainer + // currently - making it impossible to answer the question of existence or create if necessary. Thirdly, + // the Win32 API would create these folders with very specific ACLs, which even in the cases we can create + // are a significant compat risk (trying to replicate internal Windows behavior- it is documented that they + // set specific ACLs, but not which ones). + if (ApiInformation.IsTypePresent("Windows.Storage.UserDataPaths")) + { + return GetFolderPathCoreCurrent(folder); + } + else + { + return GetFolderPathCoreFallBack(folder); + } + } + + private static string GetFolderPathCoreCurrent(SpecialFolder folder) + { + // While all of these give back real paths, most of them are not accessible + // from an appcontainer currently (they will give access denied) + switch (folder) + { + case SpecialFolder.ApplicationData: + return UserDataPaths.GetDefault().RoamingAppData; + case SpecialFolder.CommonApplicationData: + return AppDataPaths.GetDefault().ProgramData; + case SpecialFolder.LocalApplicationData: + return AppDataPaths.GetDefault().LocalAppData; + case SpecialFolder.Cookies: + return AppDataPaths.GetDefault().Cookies; + case SpecialFolder.Desktop: + return AppDataPaths.GetDefault().Desktop; + case SpecialFolder.Favorites: + return AppDataPaths.GetDefault().Favorites; + case SpecialFolder.History: + return AppDataPaths.GetDefault().History; + case SpecialFolder.InternetCache: + return AppDataPaths.GetDefault().InternetCache; + case SpecialFolder.MyMusic: + return UserDataPaths.GetDefault().Music; + case SpecialFolder.MyPictures: + return UserDataPaths.GetDefault().Pictures; + case SpecialFolder.MyVideos: + return UserDataPaths.GetDefault().Videos; + case SpecialFolder.Recent: + return UserDataPaths.GetDefault().Recent; + case SpecialFolder.System: + return SystemDataPaths.GetDefault().System; + case SpecialFolder.Templates: + return UserDataPaths.GetDefault().Templates; + case SpecialFolder.DesktopDirectory: + return UserDataPaths.GetDefault().Desktop; + case SpecialFolder.Personal: + return UserDataPaths.GetDefault().Documents; + case SpecialFolder.CommonDocuments: + return SystemDataPaths.GetDefault().PublicDocuments; + case SpecialFolder.CommonMusic: + return SystemDataPaths.GetDefault().PublicMusic; + case SpecialFolder.CommonPictures: + return SystemDataPaths.GetDefault().PublicPictures; + case SpecialFolder.CommonDesktopDirectory: + return SystemDataPaths.GetDefault().PublicDesktop; + case SpecialFolder.CommonVideos: + return SystemDataPaths.GetDefault().PublicVideos; + case SpecialFolder.UserProfile: + return UserDataPaths.GetDefault().Profile; + case SpecialFolder.SystemX86: + return SystemDataPaths.GetDefault().SystemX86; + case SpecialFolder.Windows: + return SystemDataPaths.GetDefault().Windows; + + // The following aren't available on WinRT. Our default behavior + // is string.Empty for paths that aren't available. + // + // case SpecialFolder.Programs: + // case SpecialFolder.MyComputer: + // case SpecialFolder.SendTo: + // case SpecialFolder.StartMenu: + // case SpecialFolder.Startup: + // case SpecialFolder.ProgramFiles: + // case SpecialFolder.CommonProgramFiles: + // case SpecialFolder.AdminTools: + // case SpecialFolder.CDBurning: + // case SpecialFolder.CommonAdminTools: + // case SpecialFolder.CommonOemLinks: + // case SpecialFolder.CommonStartMenu: + // case SpecialFolder.CommonPrograms: + // case SpecialFolder.CommonStartup: + // case SpecialFolder.CommonTemplates: + // case SpecialFolder.Fonts: + // case SpecialFolder.NetworkShortcuts: + // case SpecialFolder.PrinterShortcuts: + // case SpecialFolder.CommonProgramFilesX86: + // case SpecialFolder.ProgramFilesX86: + // case SpecialFolder.Resources: + // case SpecialFolder.LocalizedResources: + + default: + return string.Empty; + } + } + + private static string GetFolderPathCoreFallBack(SpecialFolder folder) + { + // For testing without the new WinRT APIs. We cannot use Win32 APIs for + // special folders as they are not in the WACK. + switch (folder) + { + case SpecialFolder.ApplicationData: + return ApplicationData.Current.RoamingFolder?.Path; + case SpecialFolder.LocalApplicationData: + return ApplicationData.Current.LocalFolder?.Path; + case SpecialFolder.System: + return SystemDirectory; + case SpecialFolder.Windows: + return Path.GetDirectoryName(SystemDirectory); + default: + return string.Empty; + } + } + } +} -- 2.7.4