using System.Runtime.InteropServices; namespace SwyxTray; internal static class NativeMethods { /// /// Gibt ein von erzeugtes /// HICON frei. Ohne diesen Aufruf leckt jedes erzeugte Symbol ein /// GDI-Handle. /// /// Bewusst DllImport statt LibraryImport: Letzteres verlangt /// AllowUnsafeBlocks fuer das gesamte Projekt, was fuer diesen einen /// Aufruf unverhaeltnismaessig waere. /// [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool DestroyIcon(IntPtr hIcon); private const uint RpcCAuthnLevelNone = 1; private const uint RpcCImpLevelIdentify = 2; private const uint EoacNone = 0; /// Wurde zu spaet aufgerufen — COM war bereits gemarshallt. private const int RpcETooLate = unchecked((int)0x80010119); [DllImport("ole32.dll")] private static extern int CoInitializeEx(IntPtr pvReserved, uint dwCoInit); [DllImport("ole32.dll")] private static extern int CoInitializeSecurity( IntPtr pSecDesc, int cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, uint dwAuthnLevel, uint dwImpLevel, IntPtr pAuthList, uint dwCapabilities, IntPtr pReserved3); /// /// Erlaubt CLMgr, Ereignisse in diesen Prozess zurueckzurufen. /// /// CLMgr.exe ist ein eigener Prozess. Beim Anmelden der Ereignissenke /// (IConnectionPoint::Advise) ruft CLMgr in unseren Prozess zurueck. /// Ohne eigene Sicherheitsvorgabe verwendet COM Standardwerte, unter denen /// dieser Rueckruf mit E_ACCESSDENIED abgewiesen wird. /// /// Authentifizierungsstufe NONE bedeutet: eingehende COM-Aufrufe an diesen /// Prozess werden nicht authentifiziert. Das ist die uebliche Einstellung /// fuer COM-Ereignissenken und betrifft nur diesen Prozess, der ausser der /// Senke keine Schnittstellen nach aussen anbietet. Wer es enger fassen /// will, probiert RPC_C_AUTHN_LEVEL_CONNECT (2) — das genuegt, solange /// CLMgr in derselben Sitzung und unter demselben Konto laeuft. /// /// Muss vor dem ersten COM-Aufruf erfolgen; danach liefert Windows /// RPC_E_TOO_LATE. /// /// HRESULT des Aufrufs, 0 = Erfolg. internal static int InitializeComSecurity() { // Das Apartment steht durch [STAThread] fest; dieser Aufruf stellt nur // sicher, dass COM initialisiert ist, bevor die Sicherheit gesetzt wird. const uint coinitApartmentThreaded = 0x2; CoInitializeEx(IntPtr.Zero, coinitApartmentThreaded); return CoInitializeSecurity( IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcCAuthnLevelNone, RpcCImpLevelIdentify, IntPtr.Zero, EoacNone, IntPtr.Zero); } internal static bool IsTooLate(int hresult) => hresult == RpcETooLate; }