LoudToast.cs
|
// LoudToast native core. Compiled by LoudToast.psm1 at import time via CodeDom against System32\WinMetadata
// (C# 5, .NET Framework). The COM interfaces below are undocumented; they were reconstructed from proxy/stub // format strings and public PDB symbols of Windows 11 build 26200. using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using Windows.Data.Xml.Dom; using Windows.UI.Notifications; namespace LoudToast { // ---------- Quiet Hours / Do Not Disturb (QuietHours.dll, hosted by WpnUserService) ---------- [ComImport, Guid("6bff4732-81ec-4ffb-ae67-b6c1bc29631f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IQuietHoursSettings { [PreserveSig] int get_UserSelectedProfile([MarshalAs(UnmanagedType.LPWStr)] out string id); [PreserveSig] int put_UserSelectedProfile([MarshalAs(UnmanagedType.LPWStr)] string id); [PreserveSig] int GetProfile([MarshalAs(UnmanagedType.LPWStr)] string id, out IQuietHoursProfile p); void GetAllProfileData(); void GetDisplayNameForProfile(); [PreserveSig] int get_QuietMomentsManager(out IQuietMomentsManager m); [PreserveSig] int get_OffProfileId([MarshalAs(UnmanagedType.LPWStr)] out string id); [PreserveSig] int get_ActiveQuietMomentProfile([MarshalAs(UnmanagedType.LPWStr)] out string id); void SetActiveQuietMomentProfile(); [PreserveSig] int get_ActiveProfile([MarshalAs(UnmanagedType.LPWStr)] out string id); void get_QuietHoursPinnedContactManager(); void SetQuietMomentsShowSummaryEnabled(); void GetQuietMomentsShowSummaryEnabled(); [PreserveSig] int GetAlwaysAllowedApps(out int n, out IntPtr arr); } [ComImport, Guid("e813fe81-62b6-417d-b951-9d2e08486ac1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IQuietHoursProfile { void get_DisplayName(); void get_ProfileId(); [PreserveSig] int GetSetting(int setting, out int value); [PreserveSig] int PutSetting(int setting, int value); void _7(); void GetAllowedContacts(); void AddAllowedContact(); void RemoveAllowedContact(); [PreserveSig] int GetAllowedApps(out int n, out IntPtr arr); [PreserveSig] int AddAllowedApp([MarshalAs(UnmanagedType.LPWStr)] string aumid); [PreserveSig] int RemoveAllowedApp([MarshalAs(UnmanagedType.LPWStr)] string aumid); } [ComImport, Guid("b0217783-87b7-422c-b902-5c148c14f150"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IQuietMomentsManager { void GetAllQuietMomentModes(); void GetQuietMoment(); [PreserveSig] int TurnOffCurrentlyActiveQuietMoment(); } public static class Dnd { public const string Off = "Microsoft.QuietHoursProfile.Unrestricted"; public const string PriorityOnly = "Microsoft.QuietHoursProfile.PriorityOnly"; // the Windows 11 "Do not disturb" toggle public const string AlarmsOnly = "Microsoft.QuietHoursProfile.AlarmsOnly"; static IQuietHoursSettings Q() { return (IQuietHoursSettings)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("f53321fa-34f8-4b7f-b9a3-361877cb94cf"))); } static IQuietHoursProfile P(string id) { IQuietHoursProfile p; Marshal.ThrowExceptionForHR(Q().GetProfile(id, out p)); return p; } static string[] Strings(int n, IntPtr a) { var r = new string[n]; for (int i = 0; i < n; i++) { var p = Marshal.ReadIntPtr(a, i * IntPtr.Size); r[i] = Marshal.PtrToStringUni(p); Marshal.FreeCoTaskMem(p); } if (a != IntPtr.Zero) Marshal.FreeCoTaskMem(a); return r; } public static string UserSelected { get { string s; Marshal.ThrowExceptionForHR(Q().get_UserSelectedProfile(out s)); return s; } } // Effective profile: the more restrictive of the user's choice and an active automatic rule public static string Active { get { string s; Marshal.ThrowExceptionForHR(Q().get_ActiveProfile(out s)); return s; } } public static string QuietMomentProfile { get { string s; Marshal.ThrowExceptionForHR(Q().get_ActiveQuietMomentProfile(out s)); return s; } } public static void Set(string id) { Marshal.ThrowExceptionForHR(Q().put_UserSelectedProfile(id)); } public static void TurnOffQuietMoment() { IQuietMomentsManager m; Marshal.ThrowExceptionForHR(Q().get_QuietMomentsManager(out m)); Marshal.ThrowExceptionForHR(m.TurnOffCurrentlyActiveQuietMoment()); } public static string[] AlwaysAllowedApps() { int n; IntPtr a; Marshal.ThrowExceptionForHR(Q().GetAlwaysAllowedApps(out n, out a)); return Strings(n, a); } public static string[] PriorityApps(string profile) { int n; IntPtr a; Marshal.ThrowExceptionForHR(P(profile).GetAllowedApps(out n, out a)); return Strings(n, a); } public static void AddPriorityApp(string profile, string aumid) { Marshal.ThrowExceptionForHR(P(profile).AddAllowedApp(aumid)); } public static void RemovePriorityApp(string profile, string aumid) { Marshal.ThrowExceptionForHR(P(profile).RemoveAllowedApp(aumid)); } // 0 = calls, 1 = phone SMS (requires 0), 2 = reminders (see QuietHoursToastFilterSink::NotificationToastSlotNew) public static bool GetFlag(string profile, int i) { int v; Marshal.ThrowExceptionForHR(P(profile).GetSetting(i, out v)); return v != 0; } } // ---------- Per-app notification settings (NotificationController.dll, hosted by WpnUserService) ---------- [ComImport, Guid("443b1739-3779-4aba-953b-9e4ff84dd4b6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface INotificationSettings { [PreserveSig] int GetSettingsForAumid([MarshalAs(UnmanagedType.LPWStr)] string aumid, out IAumidNotificationSettings s); } [ComImport, Guid("9dca8f00-cb98-434b-9473-5a0691200dc4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAumidNotificationSettings { [PreserveSig] int get_Aumid([MarshalAs(UnmanagedType.LPWStr)] out string s); [PreserveSig] int get_PackageFullName([MarshalAs(UnmanagedType.LPWStr)] out string s); [PreserveSig] int get_Enabled(out int v); [PreserveSig] int put_Enabled(int v); [PreserveSig] int get_ShowBanner(out int v); [PreserveSig] int put_ShowBanner(int v); [PreserveSig] int get_ShowInActionCenter(out int v); [PreserveSig] int put_ShowInActionCenter(int v); [PreserveSig] int get_AllowContentAboveLock(out int v); [PreserveSig] int put_AllowContentAboveLock(int v); [PreserveSig] int get_AllowUrgentNotifications(out int v); [PreserveSig] int put_AllowUrgentNotifications(int v); } public static class AppSettings { static IAumidNotificationSettings S(string aumid) { var ns = (INotificationSettings)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("d18705be-fc2f-44c8-aeff-1cd49aea8fc1"))); IAumidNotificationSettings s; Marshal.ThrowExceptionForHR(ns.GetSettingsForAumid(aumid, out s)); return s; } public static Hashtable Get(string aumid) { var s = S(aumid); int v; var h = new Hashtable(); Marshal.ThrowExceptionForHR(s.get_Enabled(out v)); h["Enabled"] = v != 0; Marshal.ThrowExceptionForHR(s.get_ShowBanner(out v)); h["ShowBanner"] = v != 0; Marshal.ThrowExceptionForHR(s.get_ShowInActionCenter(out v)); h["ShowInActionCenter"] = v != 0; Marshal.ThrowExceptionForHR(s.get_AllowContentAboveLock(out v)); h["AllowContentAboveLock"] = v != 0; Marshal.ThrowExceptionForHR(s.get_AllowUrgentNotifications(out v)); h["AllowUrgent"] = v != 0; return h; } public static void Set(string aumid, string name, bool value) { var s = S(aumid); int v = value ? 1 : 0; switch (name) { case "Enabled": Marshal.ThrowExceptionForHR(s.put_Enabled(v)); break; case "ShowBanner": Marshal.ThrowExceptionForHR(s.put_ShowBanner(v)); break; case "ShowInActionCenter": Marshal.ThrowExceptionForHR(s.put_ShowInActionCenter(v)); break; case "AllowContentAboveLock": Marshal.ThrowExceptionForHR(s.put_AllowContentAboveLock(v)); break; case "AllowUrgent": Marshal.ThrowExceptionForHR(s.put_AllowUrgentNotifications(v)); break; default: throw new ArgumentException(name); } } } // ---------- Toasts (WinRT) ---------- public class ToastResult { public string Result; // Activated | Dismissed | Failed | Timeout public string Arguments; // Activated: arguments of the clicked element public Hashtable UserInput; // Activated: input id -> value public string Reason; // Dismissed: UserCanceled | ApplicationHidden | TimedOut public int ErrorCode; // Failed: HRESULT } public class ToastWaiter { readonly ManualResetEvent done = new ManualResetEvent(false); readonly ToastResult r = new ToastResult(); public ToastWaiter(ToastNotification t) { t.Activated += (s, a) => { var e = a as ToastActivatedEventArgs; if (e != null) { r.Arguments = e.Arguments; r.UserInput = new Hashtable(); try { foreach (var kv in e.UserInput) r.UserInput[kv.Key] = Convert.ToString(kv.Value); } catch { } // UserInput requires Windows 10 2004+ } Finish("Activated"); }; t.Dismissed += (s, a) => { r.Reason = a.Reason.ToString(); Finish("Dismissed"); }; t.Failed += (s, a) => { r.ErrorCode = a.ErrorCode.HResult; Finish("Failed"); }; } void Finish(string kind) { lock (r) { if (r.Result == null) r.Result = kind; } done.Set(); } public ToastResult Wait(int timeoutMs) { if (!done.WaitOne(timeoutMs)) lock (r) { if (r.Result == null) r.Result = "Timeout"; } return r; } } public static class Toasts { static XmlDocument Doc(string xml) { var d = new XmlDocument(); d.LoadXml(xml); return d; } static NotificationData Data(IDictionary values, uint seq) { var d = new NotificationData(); d.SequenceNumber = seq; foreach (DictionaryEntry kv in values) d.Values[Convert.ToString(kv.Key)] = Convert.ToString(kv.Value); return d; } public static ToastNotification Create(string xml, string tag, string group, object expiration, bool suppressPopup, bool high, bool expiresOnReboot, IDictionary data) { var t = new ToastNotification(Doc(xml)); if (!string.IsNullOrEmpty(tag)) t.Tag = tag; if (!string.IsNullOrEmpty(group)) t.Group = group; if (expiration != null) t.ExpirationTime = new DateTimeOffset((DateTime)expiration); t.SuppressPopup = suppressPopup; if (high) t.Priority = ToastNotificationPriority.High; t.ExpiresOnReboot = expiresOnReboot; if (data != null && data.Count > 0) t.Data = Data(data, 1); return t; } public static ToastWaiter Show(string appId, ToastNotification t, bool attach) { var w = attach ? new ToastWaiter(t) : null; // handlers must be attached before Show() ToastNotificationManager.CreateToastNotifier(appId).Show(t); return w; } public static void Schedule(string appId, string xml, DateTime at, string tag, string group, bool suppressPopup) { var s = new ScheduledToastNotification(Doc(xml), new DateTimeOffset(at)); if (!string.IsNullOrEmpty(tag)) s.Tag = tag; if (!string.IsNullOrEmpty(group)) s.Group = group; s.SuppressPopup = suppressPopup; ToastNotificationManager.CreateToastNotifier(appId).AddToSchedule(s); } public static string[] Scheduled(string appId) { var l = new List<string>(); foreach (var s in ToastNotificationManager.CreateToastNotifier(appId).GetScheduledToastNotifications()) l.Add(s.Tag + "|" + s.Group + "|" + s.DeliveryTime.LocalDateTime.ToString("o")); return l.ToArray(); } public static void Unschedule(string appId, string tag, string group) { var n = ToastNotificationManager.CreateToastNotifier(appId); foreach (var s in n.GetScheduledToastNotifications()) if ((string.IsNullOrEmpty(tag) || s.Tag == tag) && (string.IsNullOrEmpty(group) || s.Group == group)) n.RemoveFromSchedule(s); } public static string Update(string appId, string tag, string group, IDictionary values, uint seq) { var n = ToastNotificationManager.CreateToastNotifier(appId); var d = Data(values, seq); return (string.IsNullOrEmpty(group) ? n.Update(d, tag) : n.Update(d, tag, group)).ToString(); } public static void Remove(string appId, string tag, string group) { var h = ToastNotificationManager.History; // PowerShell passes $null as "" to string parameters if (string.IsNullOrEmpty(group)) h.Clear(appId); else if (string.IsNullOrEmpty(tag)) h.RemoveGroup(group, appId); else h.Remove(tag, group, appId); } public static Hashtable[] History(string appId) { var l = new List<Hashtable>(); foreach (var t in ToastNotificationManager.History.GetHistory(appId)) { var h = new Hashtable(); h["Tag"] = t.Tag; h["Group"] = t.Group; h["Xml"] = t.Content.GetXml(); h["ExpirationTime"] = t.ExpirationTime.HasValue ? (object)t.ExpirationTime.Value.LocalDateTime : null; l.Add(h); } return l.ToArray(); } public static string Setting(string appId) { return ToastNotificationManager.CreateToastNotifier(appId).Setting.ToString(); } } } |