using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Storage.Packaging.Appx; using Detours = Microsoft.Detours.PInvoke;
///<summary> /// Represents a hook for the <see cref="PInvoke.AppPolicyGetWindowingModel(HANDLE, AppPolicyWindowingModel*)"/> function. ///</summary> publicsealedpartialclassHookWindowingModel : IDisposable { ///<summary> /// The value that indicates whether the class has been disposed. ///</summary> privatebool disposed;
///<summary> /// The reference count for the hook. ///</summary> privatestaticint refCount;
///<summary> /// The value that represents the current process token. ///</summary> privateconstint currentProcessToken = -6;
///<summary> /// Initializes a new instance of the <see cref="HookWindowingModel"/> class. ///</summary> publicHookWindowingModel() { refCount++; StartHook(); }
///<summary> /// Finalizes this instance of the <see cref="HookWindowingModel"/> class. ///</summary> ~HookWindowingModel() { Dispose(); }
///<summary> /// Gets the value that indicates whether the hook is active. ///</summary> publicstaticbool IsHooked { get; privateset; }
///<summary> /// Gets or sets the windowing model to use when the hooked <see cref="PInvoke.AppPolicyGetWindowingModel(HANDLE, AppPolicyWindowingModel*)"/> function is called. ///</summary> internalstatic AppPolicyWindowingModel WindowingModel { get; set; } = AppPolicyWindowingModel.AppPolicyWindowingModel_ClassicDesktop;
///<summary> /// Starts the hook for the <see cref="PInvoke.AppPolicyGetWindowingModel(HANDLE, AppPolicyWindowingModel*)"/> function. ///</summary> privatestaticunsafevoidStartHook() { if (!IsHooked) { using FreeLibrarySafeHandle library = PInvoke.GetModuleHandle("KERNEL32.dll"); if (!library.IsInvalid && NativeLibrary.TryGetExport(library.DangerousGetHandle(), nameof(PInvoke.AppPolicyGetWindowingModel), outnint appPolicyGetWindowingModel)) { void* appPolicyGetWindowingModelPtr = (void*)appPolicyGetWindowingModel; delegate* unmanaged[Stdcall]<HANDLE, AppPolicyWindowingModel*, WIN32_ERROR> overrideAppPolicyGetWindowingModel = &OverrideAppPolicyGetWindowingModel;
///<param name="policy">A pointer to a variable of the <a href="https://docs.microsoft.com/windows/win32/api/appmodel/ne-appmodel-apppolicywindowingmodel">AppPolicyWindowingModel</a> enumerated type. /// When the function returns successfully, the variable contains the <see cref="WindowingModel"/> when the identified process is current; otherwise, the windowing model of the identified process.</param> ///<remarks>The overridden <see cref="PInvoke.AppPolicyGetWindowingModel(HANDLE, AppPolicyWindowingModel*)"/> function.</remarks> ///<inheritdoc cref="PInvoke.AppPolicyGetWindowingModel(HANDLE, AppPolicyWindowingModel*)"/> [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] privatestaticunsafe WIN32_ERROR OverrideAppPolicyGetWindowingModel(HANDLE processToken, AppPolicyWindowingModel* policy) { if ((int)processToken.Value == currentProcessToken) { *policy = WindowingModel; return WIN32_ERROR.ERROR_SUCCESS; } return AppPolicyGetWindowingModel(processToken, policy); }