Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Shared / MS / Win32 / ManagedWndProcTracker.cs / 1 / ManagedWndProcTracker.cs
//#define LOGGING
using System;
using System.Collections;
using System.Threading;
using System.Runtime.InteropServices;
using MS.Internal;
using System.Security;
using System.Security.Permissions;
// The SecurityHelper class differs between assemblies and could not actually be
// shared, so it is duplicated across namespaces to prevent name collision.
#if WINDOWS_BASE
using MS.Internal.WindowsBase;
#elif PRESENTATION_CORE
using MS.Internal.PresentationCore;
#elif PRESENTATIONFRAMEWORK
using MS.Internal.PresentationFramework;
#elif DRT
using MS.Internal.Drt;
#else
#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly.
#endif
namespace MS.Win32
{
internal static class ManagedWndProcTracker
{
///
/// Critical: This code calls into Link demanded methods to attach handlers
/// TreatAsSafe: This code does not take any parameter or return state.
/// It simply attaches private call back.
///
[SecurityCritical,SecurityTreatAsSafe]
static ManagedWndProcTracker()
{
// Listen for ProcessExit so we can detach ourselves when the CLR shuts down
// and avoid unmanaged code from calling back in to managed code during shutdown.
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnAppDomainProcessExit);
AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnAppDomainProcessExit);
}
///
/// Critical: Uses critical member _hwndList
///
[SecurityCritical]
internal static void TrackHwndSubclass(HwndSubclass subclass, IntPtr hwnd)
{
lock (_hwndList)
{
// We use HwndSubclass as the key and the hwnd ptr as the value.
// This supports the case where two (or more) HwndSubclasses
// get attached to the same Hwnd. At AppDomain shutdown, we may
// end up sending the Detach message to the Hwnd more than once,
// but that won't cause any harm.
_hwndList[subclass] = hwnd;
}
#if LOGGING
LogStartHWND(hwnd, "Core HwndWrapper..ctor");
#endif
}
///
/// Critical: Uses critical member _hwndList
///
[SecurityCritical]
internal static void UnhookHwndSubclass(HwndSubclass subclass)
{
// if exiting the AppDomain, ignore this call. This avoids changing
// the list during the loop in OnAppDomainProcessExit
if (_exiting)
return;
lock (_hwndList)
{
_hwndList.Remove(subclass);
}
}
///
/// Critical performs an elevation to call HookUpDefWindowProc.
/// TreatAsSafe - net effect of this is to remove our already registered WndProc's on domain shutdown.
/// safe - as you had to elevate to add these already. Removing them is considered safe.
///
[SecurityCritical, SecurityTreatAsSafe]
private static void OnAppDomainProcessExit(object sender, EventArgs e)
{
// AppDomain is exiting -- if anyone tries to call back into managed code
// after this point, bad things will happen. We must remove all unmanaged
// code references to our WndProc delegates. USER will explode if we set the
// WndProc to null, so the next most reasonable thing we can do is hook up
// the DefaultWindowProc.
//DbgUserBreakPoint();
_exiting = true;
lock (_hwndList)
{
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert:
try
{
foreach (DictionaryEntry entry in _hwndList)
{
IntPtr hwnd = (IntPtr)entry.Value;
// tell all the HwndSubclass WndProcs on this window's chain
// to detach themselves
UnsafeNativeMethods.SendMessage(hwnd, HwndSubclass.DetachMessage,
IntPtr.Zero /* wildcard */,
(IntPtr) 2 /* force and forward */);
// the last WndProc on the chain might be managed as well
// (see HwndSubclass.SubclassWndProc for explanation).
// Just in case, restore the DefaultWindowProc.
HookUpDefWindowProc(hwnd);
}
}
finally
{
CodeAccessPermission.RevertAssert();
}
}
}
///
/// TreatAsSafe: Demands for unmanaged code
/// Critical: Elevates by calling an unverifieds UnsafeNativeMethod call
///
[SecurityTreatAsSafe, SecurityCritical]
private static void HookUpDefWindowProc(IntPtr hwnd)
{
SecurityHelper.DemandUnmanagedCode();
#if LOGGING
LogFinishHWND(hwnd, "Core HookUpDWP");
#endif
IntPtr result = IntPtr.Zero ;
// We've already cleaned up, return immediately.
if (hwnd == IntPtr.Zero)
{
return;
}
IntPtr defWindowProc = GetDefWindowProcAddress(hwnd);
if (defWindowProc != IntPtr.Zero)
{
try
{
result = UnsafeNativeMethods.SetWindowLong(new HandleRef(null,hwnd), NativeMethods.GWL_WNDPROC, defWindowProc);
}
catch(System.ComponentModel.Win32Exception e)
{
// We failed to change the window proc. Now what?
if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE
{
// For debugging purposes, throw an exception so we can debug
// this and know if it's possible to call SetWindowLong on
// the wrong thread.
throw;
}
}
if (result != IntPtr.Zero )
{
UnsafeNativeMethods.PostMessage(new HandleRef(null,hwnd), NativeMethods.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
}
}
// Get the DWP for the given HWND -- returns DefWindowProcA or DefWindowProcW
// depending on IsWindowUnicode(hwnd).
private static IntPtr GetDefWindowProcAddress(IntPtr hwnd)
{
// We need to swap back in the DefWindowProc, but which one we use depends on
// what the Unicode-ness of the window.
if (SafeNativeMethods.IsWindowUnicode(new HandleRef(null,hwnd)))
{
if (_cachedDefWindowProcW == IntPtr.Zero)
{
_cachedDefWindowProcW = GetUser32ProcAddress("DefWindowProcW");
}
return _cachedDefWindowProcW;
}
else
{
if (_cachedDefWindowProcA == IntPtr.Zero)
{
_cachedDefWindowProcA = GetUser32ProcAddress("DefWindowProcA") ;
}
return _cachedDefWindowProcA;
}
}
///
/// SecurityCritical: elevates via a call to unsafe native methods
/// SecurityTreatAsSafe: Demands unmgd code permission via SecurityHelper
///
[SecurityCritical, SecurityTreatAsSafe]
private static IntPtr GetUser32ProcAddress(string export)
{
SecurityHelper.DemandUnmanagedCode();
IntPtr hModule = UnsafeNativeMethods.GetModuleHandle(ExternDll.User32);
if (hModule != IntPtr.Zero)
{
return UnsafeNativeMethods.GetProcAddress(new HandleRef(null, hModule), export);
}
return IntPtr.Zero;
}
#if LOGGING
[DllImport("ntdll.dll")]
private static extern void DbgUserBreakPoint();
[DllImport("ntdll.dll")]
private static extern void DbgPrint(string msg);
internal static void LogStartHWND(IntPtr hwnd, string fromWhere)
{
string msg = String.Format("BEGIN: {0:X} -- Setting DWP, process = {1} ({2}) {3}",
hwnd,
System.Diagnostics.Process.GetCurrentProcess().ProcessName,
fromWhere,
System.Environment.NewLine);
Log(msg);
}
internal static void LogFinishHWND(IntPtr hwnd, string fromWhere)
{
string msg = String.Format("END: {0:X} -- Setting DWP, process = {1} ({2}) {3}",
hwnd,
System.Diagnostics.Process.GetCurrentProcess().ProcessName,
fromWhere,
System.Environment.NewLine);
Log(msg);
}
private static void Log(string msg)
{
//DbgUserBreakPoint();
/*
byte[] msgBytes = System.Text.Encoding.ASCII.GetBytes(msg);
System.IO.FileStream fs = System.IO.File.Open("c:\\dwplog.txt", System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
fs.Write(msgBytes, 0, msgBytes.Length);
fs.Flush();
fs.Close();
*/
}
#endif
private static IntPtr _cachedDefWindowProcA = IntPtr.Zero;
private static IntPtr _cachedDefWindowProcW = IntPtr.Zero;
///
/// Critical - used as input to unsafe calls
///
[SecurityCritical]
private static Hashtable _hwndList = new Hashtable(10);
private static bool _exiting = false;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TransportSecurityBindingElement.cs
- ChangesetResponse.cs
- ComponentConverter.cs
- ProfileProvider.cs
- FragmentQuery.cs
- NativeActivityContext.cs
- DataServiceQueryProvider.cs
- CodeDirectiveCollection.cs
- ColumnMapCopier.cs
- TraceData.cs
- ChildDocumentBlock.cs
- FrameworkTemplate.cs
- HttpProfileGroupBase.cs
- Message.cs
- SpotLight.cs
- FreezableDefaultValueFactory.cs
- GifBitmapDecoder.cs
- ButtonChrome.cs
- ObjectDataSourceFilteringEventArgs.cs
- UserUseLicenseDictionaryLoader.cs
- MenuItemCollection.cs
- ValidatorCollection.cs
- RsaSecurityKey.cs
- ComponentManagerBroker.cs
- RadioButtonPopupAdapter.cs
- RequestResponse.cs
- PermissionAttributes.cs
- WorkflowMarkupSerializationException.cs
- Action.cs
- TextEffectResolver.cs
- ConfigurationSectionHelper.cs
- RuntimeIdentifierPropertyAttribute.cs
- FragmentQueryKB.cs
- AdRotator.cs
- SqlErrorCollection.cs
- RoutedEvent.cs
- mongolianshape.cs
- PropertyBuilder.cs
- DropDownButton.cs
- CellConstant.cs
- HMACMD5.cs
- AssemblyHelper.cs
- ServiceProviders.cs
- XmlEncoding.cs
- SizeFConverter.cs
- ViewLoader.cs
- XsltException.cs
- PropertyChangedEventManager.cs
- unsafenativemethodstextservices.cs
- TypeInfo.cs
- GridViewEditEventArgs.cs
- ButtonBaseDesigner.cs
- ElementHost.cs
- cache.cs
- DragStartedEventArgs.cs
- InstanceContextManager.cs
- PocoPropertyAccessorStrategy.cs
- PrintPreviewControl.cs
- NextPreviousPagerField.cs
- ErrorHandler.cs
- AggregateNode.cs
- TreeIterator.cs
- ButtonChrome.cs
- ToolboxItemSnapLineBehavior.cs
- BufferedStream2.cs
- ContainerActivationHelper.cs
- WsatServiceCertificate.cs
- FlowPosition.cs
- MultiView.cs
- BindingContext.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- LayoutEngine.cs
- ConfigurationLocationCollection.cs
- AccessorTable.cs
- EnumerableRowCollection.cs
- KeyBinding.cs
- ColumnMapCopier.cs
- HebrewCalendar.cs
- ServiceNameElement.cs
- DbFunctionCommandTree.cs
- Sql8ExpressionRewriter.cs
- QuaternionValueSerializer.cs
- FrameworkContentElement.cs
- TrustManagerMoreInformation.cs
- PageStatePersister.cs
- Stackframe.cs
- ReferenceList.cs
- EncryptedPackage.cs
- HttpHandlerActionCollection.cs
- SafeRegistryHandle.cs
- SqlHelper.cs
- InputLanguageCollection.cs
- GridViewColumnHeader.cs
- CalendarDataBindingHandler.cs
- InternalsVisibleToAttribute.cs
- Int16AnimationUsingKeyFrames.cs
- WindowsBrush.cs
- DesignerAdapterAttribute.cs
- DBNull.cs
- DBParameter.cs