JD2022-TU1/main/tools/framework/JD.MessageService/EnableThemingInScope.cs

150 lines
4.8 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms;
namespace JD.MessageService
{
// http://support.microsoft.com/kb/830033
// http://stackoverflow.com/questions/1612351/entrypointnotfoundexception-when-using-taskdialog-in-c-sharp
[SuppressUnmanagedCodeSecurity]
internal class EnableThemingInScope : IDisposable
{
#region Variables
private UIntPtr m_cookie;
private static ACTCTX ms_enableThemingActivationContext;
private static IntPtr ms_hActCtx;
private static bool ms_contextCreationSucceeded;
#endregion
public EnableThemingInScope()
{
m_cookie = UIntPtr.Zero;
if (OSFeature.Feature.IsPresent(OSFeature.Themes))
{
if (EnsureActivateContextCreated())
{
if (!ActivateActCtx(ms_hActCtx, out m_cookie))
{
// Be sure cookie always zero if activation failed
m_cookie = UIntPtr.Zero;
}
}
}
}
~EnableThemingInScope()
{
Dispose(false);
}
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (m_cookie != UIntPtr.Zero)
{
if (DeactivateActCtx(0, m_cookie))
{
// deactivation succeeded...
m_cookie = UIntPtr.Zero;
}
}
}
private static bool EnsureActivateContextCreated()
{
if (!ms_contextCreationSucceeded)
{
// Pull manifest from the .NET Framework install
// directory
string assemblyLoc;
FileIOPermission fiop = new FileIOPermission(PermissionState.None)
{
AllFiles = FileIOPermissionAccess.PathDiscovery
};
fiop.Assert();
try
{
assemblyLoc = typeof(Object).Assembly.Location;
}
finally
{
CodeAccessPermission.RevertAssert();
}
string manifestLoc = null;
string installDir = null;
if (assemblyLoc != null)
{
installDir = Path.GetDirectoryName(assemblyLoc);
const string manifestName = "XPThemes.manifest";
manifestLoc = Path.Combine(installDir, manifestName);
}
if (manifestLoc != null && installDir != null)
{
ms_enableThemingActivationContext = new ACTCTX
{
cbSize = Marshal.SizeOf(typeof(ACTCTX)),
lpSource = manifestLoc,
lpAssemblyDirectory = installDir,
dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
};
// Set the lpAssemblyDirectory to the install
// directory to prevent Win32 Side by Side from
// looking for comctl32 in the application
// directory, which could cause a bogus dll to be
// placed there and open a security hole.
// Note this will fail gracefully if file specified
// by manifestLoc doesn't exist.
ms_hActCtx = CreateActCtx(ref ms_enableThemingActivationContext);
ms_contextCreationSucceeded = (ms_hActCtx != new IntPtr(-1));
}
}
// If we return false, we'll try again on the next call into
// EnsureActivateContextCreated(), which is fine.
return ms_contextCreationSucceeded;
}
// All the pinvoke goo...
[DllImport("Kernel32.dll")]
private extern static IntPtr CreateActCtx(ref ACTCTX actctx);
[DllImport("Kernel32.dll")]
private extern static bool ActivateActCtx(IntPtr hActCtx, out UIntPtr lpCookie);
[DllImport("Kernel32.dll")]
private extern static bool DeactivateActCtx(uint dwFlags, UIntPtr lpCookie);
private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;
private struct ACTCTX
{
public int cbSize;
public uint dwFlags;
public string lpSource;
public ushort wProcessorArchitecture;
public ushort wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
}
}
}