150 lines
4.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|