diff --git a/src/ManagedShell.Common/Helpers/EnvironmentHelper.cs b/src/ManagedShell.Common/Helpers/EnvironmentHelper.cs index 3b24982c..0c007cd3 100644 --- a/src/ManagedShell.Common/Helpers/EnvironmentHelper.cs +++ b/src/ManagedShell.Common/Helpers/EnvironmentHelper.cs @@ -109,6 +109,19 @@ public static bool IsWindows10RS4OrBetter } } + public static bool IsWindows1020H1OrBetter + { + get + { + if (osVersionMajor == 0) + { + getOSVersion(); + } + + return (osVersionMajor >= 10 && osVersionBuild >= 19041); + } + } + public static bool IsWindows11OrBetter { get @@ -135,6 +148,19 @@ public static bool IsWindows1122H2OrBetter } } + public static bool IsWindows1124H2OrBetter + { + get + { + if (osVersionMajor == 0) + { + getOSVersion(); + } + + return (osVersionMajor >= 10 && osVersionBuild >= 26100); + } + } + public static bool IsWindows10DarkModeSupported { get diff --git a/src/ManagedShell.Interop/NativeMethods.ShlwApi.cs b/src/ManagedShell.Interop/NativeMethods.ShlwApi.cs index 197063aa..1236a6cc 100644 --- a/src/ManagedShell.Interop/NativeMethods.ShlwApi.cs +++ b/src/ManagedShell.Interop/NativeMethods.ShlwApi.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Text; namespace ManagedShell.Interop { @@ -18,5 +19,8 @@ public partial class NativeMethods [DllImport(ShlwApi_DllName, SetLastError = true)] public static extern bool SHUnlockShared(IntPtr pvData); + + [DllImport(ShlwApi_DllName, BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)] + public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved); } } diff --git a/src/ManagedShell.UWPInterop/ImmersiveShellHelper.cs b/src/ManagedShell.UWPInterop/ImmersiveShellHelper.cs new file mode 100644 index 00000000..e0b7ab87 --- /dev/null +++ b/src/ManagedShell.UWPInterop/ImmersiveShellHelper.cs @@ -0,0 +1,406 @@ +using ManagedShell.Common.Helpers; +using ManagedShell.Common.Logging; +using ManagedShell.UWPInterop.Interfaces; +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop +{ + public static class ImmersiveShellHelper + { + private static Guid CLSID_ShellExperienceManagerFactory = new Guid("2e8fcb18-a0ee-41ad-8ef8-77fb3a370ca5"); + private static Guid IID_ActionCenterExperienceManager = new Guid("df65db57-d504-456e-8bd7-004ce308d8d9"); + private static Guid IID_ControlCenterExperienceManager = new Guid("d669a58e-6b18-4d1d-9004-a8862adb0a20"); + private static Guid IID_NetworkFlyoutExperienceManager = new Guid("e44f17e6-ab85-409c-8d01-17d74bec150e"); + private static Guid IID_NetworkFlyoutExperienceManager_20H1 = new Guid("c9ddc674-b44b-4c67-9d79-2b237d9be05a"); + private static Guid IID_TrayBatteryFlyoutExperienceManager = new Guid("0a73aedc-1c68-410d-8d53-63af80951e8f"); + private static Guid IID_TrayClockFlyoutExperienceManager = new Guid("b1604325-6b59-427b-bf1b-80a2db02d3d8"); + private static Guid IID_TrayMtcUvcFlyoutExperienceManager = new Guid("7154c95d-c519-49bd-a97e-645bbfabe111"); + + private static Interfaces.IServiceProvider _immersiveShell; + private static IShellExperienceManagerFactory _shellExperienceManagerFactory; + private static IActionCenterExperienceManager _actionCenterExperienceManager; + private static IControlCenterExperienceManager _controlCenterExperienceManager; + private static INetworkFlyoutExperienceManager _networkFlyoutExperienceManager; + private static INetworkFlyoutExperienceManager_20H1 _networkFlyoutExperienceManager_20H1; + private static ITrayBatteryFlyoutExperienceManager _trayBatteryFlyoutExperienceManager; + private static ITrayClockFlyoutExperienceManager _trayClockFlyoutExperienceManager; + private static ITrayMtcUvcFlyoutExperienceManager _trayMtcUvcFlyoutExperienceManager; + + public static void AllowExplorerFocus() + { + // When invoking a flyout, the shell will attempt to make it the foreground window. + // When that fails, the flyout may not show, or input may not work as expected. + // Explicity allow Explorer to do this so that flyouts work consistently. + try + { + Interop.NativeMethods.GetWindowThreadProcessId(Interop.NativeMethods.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", "Program Manager"), out uint procId); + Interop.NativeMethods.AllowSetForegroundWindow(procId); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to allow Explorer to set the foreground window: {ex}"); + } + } + + #region Interface helpers + public static Interfaces.IServiceProvider GetImmersiveShell() + { + if (!EnvironmentHelper.IsWindows10OrBetter) + { + ShellLogger.Error("ImmersiveShell: ImmersiveShell unsupported"); + return null; + } + + try + { + _immersiveShell ??= (Interfaces.IServiceProvider)new CImmersiveShell(); + return _immersiveShell; + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to create ImmersiveShell: {ex}"); + return null; + } + } + + public static IShellExperienceManagerFactory GetShellExperienceManagerFactory() + { + if (!EnvironmentHelper.IsWindows10OrBetter) + { + ShellLogger.Error("ImmersiveShell: IShellExperienceManagerFactory unsupported"); + return null; + } + + try + { + if (GetImmersiveShell().QueryService(CLSID_ShellExperienceManagerFactory, CLSID_ShellExperienceManagerFactory, out object factoryObj) == 0) + { + return (IShellExperienceManagerFactory)factoryObj; + } + + ShellLogger.Warning("ImmersiveShell: Unable to query IShellExperienceManagerFactory"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to create IShellExperienceManagerFactory: {ex}"); + } + return null; + } + + internal static IntPtr GetExperienceManagerFromFactory(string experienceManager) + { + _shellExperienceManagerFactory ??= GetShellExperienceManagerFactory(); + if (_shellExperienceManagerFactory == null) return IntPtr.Zero; + + try + { + IntPtr hString = IntPtr.Zero; + if (NativeMethods.WindowsCreateString(experienceManager, experienceManager.Length, ref hString) != 0) + { + ShellLogger.Warning("ImmersiveShell: Unable to create experience manager string"); + return IntPtr.Zero; + } + + _shellExperienceManagerFactory.GetExperienceManager(hString, out IntPtr pExperienceManagerInterface); + NativeMethods.WindowsDeleteString(hString); + return pExperienceManagerInterface; + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to create experience manager: {ex}"); + return IntPtr.Zero; + } + } + + public static IActionCenterExperienceManager GetActionCenterExperienceManager() + { + if (!EnvironmentHelper.IsWindows10OrBetter) + { + ShellLogger.Error("ImmersiveShell: IActionCenterExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.ActionCenter"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_ActionCenterExperienceManager, out IntPtr pActionCenterManager) == 0) + { + return (IActionCenterExperienceManager)Marshal.GetObjectForIUnknown(pActionCenterManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query IActionCenterExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get IActionCenterExperienceManager: {ex}"); + } + return null; + } + + public static IControlCenterExperienceManager GetControlCenterExperienceManager() + { + if (!EnvironmentHelper.IsWindows11OrBetter || EnvironmentHelper.IsWindows1124H2OrBetter) + { + ShellLogger.Error("ImmersiveShell: IControlCenterExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.ControlCenter"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_ControlCenterExperienceManager, out IntPtr pControlCenterManager) == 0) + { + return (IControlCenterExperienceManager)Marshal.GetObjectForIUnknown(pControlCenterManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query IControlCenterExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get IControlCenterExperienceManager: {ex}"); + } + return null; + } + + internal static INetworkFlyoutExperienceManager GetNetworkExperienceManager() + { + if (!EnvironmentHelper.IsWindows10OrBetter || EnvironmentHelper.IsWindows1020H1OrBetter) + { + ShellLogger.Error("ImmersiveShell: INetworkFlyoutExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.NetworkFlyout"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_NetworkFlyoutExperienceManager, out IntPtr pNetworkManager) == 0) + { + return (INetworkFlyoutExperienceManager)Marshal.GetObjectForIUnknown(pNetworkManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query INetworkFlyoutExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get INetworkFlyoutExperienceManager: {ex}"); + } + return null; + } + + internal static INetworkFlyoutExperienceManager_20H1 GetNetworkExperienceManager_20H1() + { + if (!EnvironmentHelper.IsWindows1020H1OrBetter) + { + ShellLogger.Error("ImmersiveShell: INetworkFlyoutExperienceManager_20H1 unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.NetworkFlyout"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_NetworkFlyoutExperienceManager_20H1, out IntPtr pNetworkManager) == 0) + { + return (INetworkFlyoutExperienceManager_20H1)Marshal.GetObjectForIUnknown(pNetworkManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query INetworkFlyoutExperienceManager_20H1"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get INetworkFlyoutExperienceManager_20H1: {ex}"); + } + return null; + } + + internal static ITrayBatteryFlyoutExperienceManager GetBatteryExperienceManager() + { + if (!EnvironmentHelper.IsWindows10OrBetter || EnvironmentHelper.IsWindows1124H2OrBetter) + { + ShellLogger.Error("ImmersiveShell: ITrayBatteryFlyoutExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.TrayBatteryFlyout"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_TrayBatteryFlyoutExperienceManager, out IntPtr pBatteryManager) == 0) + { + return (ITrayBatteryFlyoutExperienceManager)Marshal.GetObjectForIUnknown(pBatteryManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query ITrayBatteryFlyoutExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get ITrayBatteryFlyoutExperienceManager: {ex}"); + } + return null; + } + + internal static ITrayClockFlyoutExperienceManager GetTrayClockFlyoutExperienceManager() + { + if (!EnvironmentHelper.IsWindows10OrBetter) + { + ShellLogger.Error("ImmersiveShell: ITrayClockFlyoutExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.TrayClockFlyout"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_TrayClockFlyoutExperienceManager, out IntPtr pClockFlyoutManager) == 0) + { + return (ITrayClockFlyoutExperienceManager)Marshal.GetObjectForIUnknown(pClockFlyoutManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query ITrayClockFlyoutExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get ITrayClockFlyoutExperienceManager: {ex}"); + } + return null; + } + + internal static ITrayMtcUvcFlyoutExperienceManager GetMtcUtcExperienceManager() + { + if (!EnvironmentHelper.IsWindows10OrBetter) + { + ShellLogger.Error("ImmersiveShell: ITrayMtcUvcFlyoutExperienceManager unsupported"); + return null; + } + + try + { + IntPtr pExperienceManagerInterface = GetExperienceManagerFromFactory("Windows.Internal.ShellExperience.MtcUvc"); + if (pExperienceManagerInterface == IntPtr.Zero) return null; + + if (Marshal.QueryInterface(pExperienceManagerInterface, ref IID_TrayMtcUvcFlyoutExperienceManager, out IntPtr pMtcUvcManager) == 0) + { + return (ITrayMtcUvcFlyoutExperienceManager)Marshal.GetObjectForIUnknown(pMtcUvcManager); + } + + ShellLogger.Warning("ImmersiveShell: Unable to query ITrayMtcUvcFlyoutExperienceManager"); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to get ITrayMtcUvcFlyoutExperienceManager: {ex}"); + } + return null; + } + #endregion + + #region Experience manager helpers + public static void ShowBatteryFlyout(Interop.NativeMethods.Rect anchorRect) + { + _trayBatteryFlyoutExperienceManager ??= GetBatteryExperienceManager(); + AllowExplorerFocus(); + + try + { + _trayBatteryFlyoutExperienceManager?.ShowFlyout(new Windows.Foundation.Rect(anchorRect.Left, anchorRect.Top, anchorRect.Width, anchorRect.Height)); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show battery flyout: {ex}"); + } + } + + public static void ShowClockFlyout(Interop.NativeMethods.Rect anchorRect) + { + _trayClockFlyoutExperienceManager ??= GetTrayClockFlyoutExperienceManager(); + AllowExplorerFocus(); + + try + { + _trayClockFlyoutExperienceManager?.ShowFlyout(new Windows.Foundation.Rect(anchorRect.Left, anchorRect.Top, anchorRect.Width, anchorRect.Height)); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show clock flyout: {ex}"); + } + } + + public static void ShowSoundFlyout(Interop.NativeMethods.Rect anchorRect) + { + _trayMtcUvcFlyoutExperienceManager ??= GetMtcUtcExperienceManager(); + AllowExplorerFocus(); + + try + { + _trayMtcUvcFlyoutExperienceManager?.ShowFlyout(new Windows.Foundation.Rect(anchorRect.Left, anchorRect.Top, anchorRect.Width, anchorRect.Height)); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show sound flyout: {ex}"); + } + } + + public static void ShowNetworkFlyout(Interop.NativeMethods.Rect anchorRect) + { + AllowExplorerFocus(); + + try + { + if (EnvironmentHelper.IsWindows1020H1OrBetter) + { + _networkFlyoutExperienceManager_20H1 ??= GetNetworkExperienceManager_20H1(); + _networkFlyoutExperienceManager_20H1?.ShowFlyout(new Windows.Foundation.Rect(anchorRect.Left, anchorRect.Top, anchorRect.Width, anchorRect.Height), 0); + } + else + { + _networkFlyoutExperienceManager ??= GetNetworkExperienceManager(); + _networkFlyoutExperienceManager?.ShowFlyout(new Windows.Foundation.Rect(anchorRect.Left, anchorRect.Top, anchorRect.Width, anchorRect.Height)); + } + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show network flyout: {ex}"); + } + } + + public static void ShowActionCenter() + { + _actionCenterExperienceManager ??= GetActionCenterExperienceManager(); + AllowExplorerFocus(); + + try + { + _actionCenterExperienceManager?.HotKeyInvoked(0); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show action center: {ex}"); + } + } + + public static void ShowControlCenter() + { + _controlCenterExperienceManager ??= GetControlCenterExperienceManager(); + AllowExplorerFocus(); + + try + { + _controlCenterExperienceManager?.HotKeyInvoked(0); + } + catch (Exception ex) + { + ShellLogger.Warning($"ImmersiveShell: Unable to show control center: {ex}"); + } + } + #endregion + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/CImmersiveShell.cs b/src/ManagedShell.UWPInterop/Interfaces/CImmersiveShell.cs new file mode 100644 index 00000000..1d79312a --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/CImmersiveShell.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport] + [Guid("c2f03a33-21f5-47fa-b4bb-156362a2f239")] + [ClassInterface(ClassInterfaceType.None)] + public class CImmersiveShell + { + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/IActionCenterExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/IActionCenterExperienceManager.cs new file mode 100644 index 00000000..3a71a94f --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/IActionCenterExperienceManager.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("df65db57-d504-456e-8bd7-004ce308d8d9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IActionCenterExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void HotKeyInvoked(int kind); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/IControlCenterExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/IControlCenterExperienceManager.cs new file mode 100644 index 00000000..0e9da626 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/IControlCenterExperienceManager.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("d669a58e-6b18-4d1d-9004-a8862adb0a20"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IControlCenterExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void HotKeyInvoked(int kind); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager.cs new file mode 100644 index 00000000..61823875 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("e44f17e6-ab85-409c-8d01-17d74bec150e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface INetworkFlyoutExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void ShowFlyout(Windows.Foundation.Rect rect); + void HideFlyout(); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager_20H1.cs b/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager_20H1.cs new file mode 100644 index 00000000..3061b0d8 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/INetworkFlyoutExperienceManager_20H1.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("c9ddc674-b44b-4c67-9d79-2b237d9be05a"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface INetworkFlyoutExperienceManager_20H1 + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void ShowFlyout(Windows.Foundation.Rect rect, int unk); + void HideFlyout(); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/IServiceProvider.cs b/src/ManagedShell.UWPInterop/Interfaces/IServiceProvider.cs new file mode 100644 index 00000000..c26e66a6 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/IServiceProvider.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport] + [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IServiceProvider + { + int QueryService(ref Guid guidService, ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/IShellExperienceManagerFactory.cs b/src/ManagedShell.UWPInterop/Interfaces/IShellExperienceManagerFactory.cs new file mode 100644 index 00000000..b8c43e1f --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/IShellExperienceManagerFactory.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("2e8fcb18-a0ee-41ad-8ef8-77fb3a370ca5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IShellExperienceManagerFactory + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void GetExperienceManager(IntPtr hStrExperience, out IntPtr pp); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/ITrayBatteryFlyoutExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/ITrayBatteryFlyoutExperienceManager.cs new file mode 100644 index 00000000..c2dad024 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/ITrayBatteryFlyoutExperienceManager.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("0a73aedc-1c68-410d-8d53-63af80951e8f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ITrayBatteryFlyoutExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void ShowFlyout(Windows.Foundation.Rect rect); + void HideFlyout(); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/ITrayClockFlyoutExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/ITrayClockFlyoutExperienceManager.cs new file mode 100644 index 00000000..557e0745 --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/ITrayClockFlyoutExperienceManager.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("b1604325-6b59-427b-bf1b-80a2db02d3d8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ITrayClockFlyoutExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void ShowFlyout(Windows.Foundation.Rect rect); + void HideFlyout(); + } +} diff --git a/src/ManagedShell.UWPInterop/Interfaces/ITrayMtcUvcFlyoutExperienceManager.cs b/src/ManagedShell.UWPInterop/Interfaces/ITrayMtcUvcFlyoutExperienceManager.cs new file mode 100644 index 00000000..310af48c --- /dev/null +++ b/src/ManagedShell.UWPInterop/Interfaces/ITrayMtcUvcFlyoutExperienceManager.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop.Interfaces +{ + [ComImport, Guid("7154c95d-c519-49bd-a97e-645bbfabe111"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ITrayMtcUvcFlyoutExperienceManager + { + void GetIids(out int iidCount, out IntPtr iids); + void GetRuntimeClassName(out IntPtr className); + void GetTrustLevel(out int trustLevel); + + void ShowFlyout(Windows.Foundation.Rect rect); + void HideFlyout(); + } +} diff --git a/src/ManagedShell.UWPInterop/ManagedShell.UWPInterop.csproj b/src/ManagedShell.UWPInterop/ManagedShell.UWPInterop.csproj index ef4b0886..25e14d36 100644 --- a/src/ManagedShell.UWPInterop/ManagedShell.UWPInterop.csproj +++ b/src/ManagedShell.UWPInterop/ManagedShell.UWPInterop.csproj @@ -19,6 +19,7 @@ + diff --git a/src/ManagedShell.UWPInterop/NativeMethods.cs b/src/ManagedShell.UWPInterop/NativeMethods.cs new file mode 100644 index 00000000..a71e9145 --- /dev/null +++ b/src/ManagedShell.UWPInterop/NativeMethods.cs @@ -0,0 +1,17 @@ +using System; +using System.Runtime.InteropServices; + +namespace ManagedShell.UWPInterop +{ + internal class NativeMethods + { + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] + public static extern int WindowsCreateString( + [MarshalAs(UnmanagedType.LPWStr)] string sourceString, + int length, + ref IntPtr hstring); + + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] + public static extern int WindowsDeleteString(IntPtr hstring); + } +} diff --git a/src/ManagedShell.UWPInterop/StoreAppHelper.cs b/src/ManagedShell.UWPInterop/StoreAppHelper.cs index 2b1b28fd..f179ff22 100644 --- a/src/ManagedShell.UWPInterop/StoreAppHelper.cs +++ b/src/ManagedShell.UWPInterop/StoreAppHelper.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Xml; using ManagedShell.Common.Enums; @@ -395,14 +394,11 @@ internal static StoreApp GetStoreApp(string appUserModelId) return null; } - [DllImport("shlwapi.dll", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)] - private static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved); - internal static string ExtractStringFromPRIFile(string pathToPRI, string resourceKey) { string sWin8ManifestString = $"@{{{pathToPRI}? {resourceKey}}}"; var outBuff = new StringBuilder(256); - int result = SHLoadIndirectString(sWin8ManifestString, outBuff, outBuff.Capacity, IntPtr.Zero); + int result = Interop.NativeMethods.SHLoadIndirectString(sWin8ManifestString, outBuff, outBuff.Capacity, IntPtr.Zero); return outBuff.ToString(); } }