Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Input / Stylus / PenContext.cs / 1305600 / PenContext.cs
using System;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Collections;
using System.Collections.Generic;
using System.Security;
using System.Security.Permissions;
using MS.Internal;
using MS.Win32.Penimc;
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
namespace System.Windows.Input
{
/////////////////////////////////////////////////////////////////////////
internal sealed class PenContext
{
///
/// Critical - Handles security critical data pimcContext, hwnd, and commHandle that
/// is created under elavated priviledge.
/// Called directly by TabletDevice.CreateContext().
/// TreatAsSafe boundry is Stylus.EnableCore, Stylus.RegisterHwndForInput
/// and HwndWrapperHook class (via HwndSource.InputFilterMessage).
///
[SecurityCritical]
internal PenContext(IPimcContext pimcContext, IntPtr hwnd,
PenContexts contexts, bool supportInRange, bool isIntegrated,
int id, IntPtr commHandle, int tabletDeviceId)
{
_contexts = contexts;
_pimcContext = new SecurityCriticalDataClass(pimcContext);
_id = id;
_tabletDeviceId = tabletDeviceId;
_commHandle = new SecurityCriticalData(commHandle);
_hwnd = new SecurityCriticalData(hwnd);
_supportInRange = supportInRange;
_isIntegrated = isIntegrated;
}
/////////////////////////////////////////////////////////////////////
~PenContext()
{
Dispose();
}
/////////////////////////////////////////////////////////////////////
///
/// Handles clean up of internal object data.
///
///
/// Critical - Calls critical code Disable.
/// Called by Finalizer.
/// TreatAsSafe - Handles critical data but does not expose it.
/// - No critical data returned or accepted as input.
///
[SecurityCritical, SecurityTreatAsSafe]
void Dispose()
{
Disable(false /*shutdownWorkerThread*/); // Make sure we remove the context from the active list.
_pimcContext = null;
_contexts = null;
GC.KeepAlive(this);
}
/////////////////////////////////////////////////////////////////////
///
/// Critical: Accesses and returns SecurityCritical data _contexts.
///
internal PenContexts Contexts
{
[SecurityCritical]
get
{
return _contexts;
}
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Critical since it returns critical data.
///
internal IntPtr CommHandle
{
[SecurityCritical]
get
{
return _commHandle.Value;
}
}
/////////////////////////////////////////////////////////////////////
internal int Id
{
get
{
return _id;
}
}
/////////////////////////////////////////////////////////////////////
internal int TabletDeviceId
{
get
{
return _tabletDeviceId;
}
}
/////////////////////////////////////////////////////////////////////////
internal StylusPointDescription StylusPointDescription
{
get
{
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
return _stylusPointDescription;
}
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Critical since it calls into unmanaged code (GetPacketPropertyInfo
/// GetPacketButtonInfo and GetPacketDescriptionInfo PenImc.dll
/// methods on IPimcContext COM interfaces stored in _pimcContext) that
/// is SecurityCritical with SUC attribute.
/// TreatAsSafe - Takes no input and returns StylusPointDescription that is handed out publically
/// on StylusEvents. Nothing inside StylusPointDescription is security critical.
///
[SecurityCritical,SecurityTreatAsSafe]
private void InitStylusPointDescription()
{
int cProps;
int cButtons;
int pressureIndex = -1;
// Make sure we are never called on the application thread when we need to talk
// to penimc or else we can cause reentrancy!
Debug.Assert(!_contexts._inputSource.Value.CheckAccess());
// We should always have a valid IPimcContext interface pointer.
Debug.Assert(_pimcContext != null && _pimcContext.Value != null);
_pimcContext.Value.GetPacketDescriptionInfo(out cProps, out cButtons); // Calls Unmanaged code - SecurityCritical with SUC.
List propertyInfos = new List(cProps + cButtons + 3);
for (int i = 0; i < cProps; i++)
{
Guid guid;
int min, max;
int units;
float res;
_pimcContext.Value.GetPacketPropertyInfo(i, out guid, out min, out max, out units, out res); // Calls Unmanaged code - SecurityCritical with SUC.
if (pressureIndex == -1 && guid == StylusPointPropertyIds.NormalPressure)
{
pressureIndex = i;
}
if (_statusPropertyIndex == -1 && guid == StylusPointPropertyIds.PacketStatus)
{
_statusPropertyIndex = i;
}
StylusPointPropertyInfo propertyInfo = new StylusPointPropertyInfo(new StylusPointProperty(guid, false), min, max, (StylusPointPropertyUnit)units, res);
propertyInfos.Add(propertyInfo);
}
Debug.Assert(_statusPropertyIndex != -1); // We should always see this.
// Make sure we actually created propertyInfos OK
if (propertyInfos != null)
{
for (int i = 0; i < cButtons; i++)
{
Guid buttonGuid;
_pimcContext.Value.GetPacketButtonInfo(i, out buttonGuid); // Calls Unmanaged code - SecurityCritical with SUC.
StylusPointProperty buttonProperty = new StylusPointProperty(buttonGuid, true);
StylusPointPropertyInfo buttonInfo = new StylusPointPropertyInfo(buttonProperty);
propertyInfos.Add(buttonInfo);
}
//validate we can never get X, Y at index != 0, 1
Debug.Assert(propertyInfos[StylusPointDescription.RequiredXIndex /*0*/].Id == StylusPointPropertyIds.X, "X isn't where we expect it! Fix PenImc to ask for X at index 0");
Debug.Assert(propertyInfos[StylusPointDescription.RequiredYIndex /*0*/].Id == StylusPointPropertyIds.Y, "Y isn't where we expect it! Fix PenImc to ask for Y at index 1");
Debug.Assert(pressureIndex == -1 || pressureIndex == StylusPointDescription.RequiredPressureIndex /*2*/,
"Fix PenImc to ask for NormalPressure at index 2!");
if (pressureIndex == -1)
{
//pressure wasn't found. Add it
propertyInfos.Insert(StylusPointDescription.RequiredPressureIndex /*2*/, StylusPointPropertyInfoDefaults.NormalPressure);
}
_infoX = propertyInfos[0];
_infoY = propertyInfos[1];
_stylusPointDescription = new StylusPointDescription(propertyInfos, pressureIndex);
}
}
///
/// Critical - Calls SecurityCritical code PenThreadPool.GetPenThreadForPenContext().
/// Accesses SecurityCriticalData _pimcContext.Value and sets _penThreadPenContext.
/// Called by PenContexts.Enable().
/// TreatAsSafe boundry is Stylus.EnableCore, Stylus.RegisterHwndForInput
/// and HwndWrapperHook class (via HwndSource.InputFilterMessage).
///
[SecurityCritical]
internal void Enable()
{
if (_pimcContext != null && _pimcContext.Value != null)
{
_penThreadPenContext = PenThreadPool.GetPenThreadForPenContext(this);
}
}
///
/// Critical - Calls SecurityCritical code (PenThread.RemovePenContext).
/// Called by PenContexts.RemoveContext and PenContexts.Disable.
///
[SecurityCritical]
internal void Disable(bool shutdownWorkerThread)
{
// Note that we should always be called under a Dispatcher.DisableProcessing.
if (_penThreadPenContext != null)
{
if (_penThreadPenContext.RemovePenContext(this))
{
_pimcContext = null; // Make sure we release wisptis ref if we removed it (ie - not in use).
// Check if we need to shut down our pen thread.
if (shutdownWorkerThread)
{
_penThreadPenContext.Dispose();
}
_penThreadPenContext = null; // Can't free this ref until we can remove this context or else we won't see the stylus OutOfRange.
}
}
}
/////////////////////////////////////////////////////////////////////
internal bool SupportInRange
{
get
{
return _supportInRange;
}
}
internal bool IsInRange(int stylusPointerId)
{
// zero is a special case where we want to know if any stylus devices are in range.
if (stylusPointerId == 0)
return _stylusDevicesInRange != null && _stylusDevicesInRange.Count > 0;
else
return (_stylusDevicesInRange != null && _stylusDevicesInRange.Contains(stylusPointerId));
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code PenContexts.OnPenDown.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FirePenDown (int stylusPointerId, int[] data, int timestamp)
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
_contexts.OnPenDown(this, _tabletDeviceId, stylusPointerId, data, timestamp);
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code PenContext.OnPenUp.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FirePenUp (int stylusPointerId, int[] data, int timestamp)
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
_contexts.OnPenUp(this, _tabletDeviceId, stylusPointerId, data, timestamp);
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code PenContexts.OnPackets and PenContexts.OnInAirPackets.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FirePackets(int stylusPointerId, int[] data, int timestamp)
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
bool fDownPackets = false;
if (_statusPropertyIndex != -1)
{
int status = data[_statusPropertyIndex]; // (we take status of the first packet for status of all of them)
fDownPackets = (status & 1/*IP_CURSOR_DOWN*/) != 0;
}
if (fDownPackets)
{
_contexts.OnPackets(this, _tabletDeviceId, stylusPointerId, data, timestamp);
}
else
{
_contexts.OnInAirPackets(this, _tabletDeviceId, stylusPointerId, data, timestamp);
}
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code PenContexts.OnPenInRange.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FirePenInRange(int stylusPointerId, int[] data, int timestamp)
{
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
// Special case where we want to forward this to the application early (this is the real
// stylus InRange event we don't currently use).
if (data == null)
{
_lastInRangeTime = timestamp; // Always reset timestamp on InRange!! Don't call EnsureTimestampUnique.
_queuedInRangeCount++;
_contexts.OnPenInRange(this, _tabletDeviceId, stylusPointerId, data, timestamp);
return;
}
// This should not be called if this stylus ID is 0
System.Diagnostics.Debug.Assert(stylusPointerId != 0);
if (!IsInRange(stylusPointerId))
{
_lastInRangeTime = timestamp; // Always reset timestamp on InRange!! Don't call EnsureTimestampUnique.
if (_stylusDevicesInRange == null)
{
_stylusDevicesInRange = new List(); // create it as needed.
}
_stylusDevicesInRange.Add(stylusPointerId);
_contexts.OnPenInRange(this, _tabletDeviceId, stylusPointerId, data, timestamp);
}
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code PenContexts.OnPenOutOfRange.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FirePenOutOfRange(int stylusPointerId, int timestamp)
{
// We only do work here if we truly had a stylus in range.
if (stylusPointerId != 0)
{
if (IsInRange(stylusPointerId))
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
_stylusDevicesInRange.Remove(stylusPointerId);
_contexts.OnPenOutOfRange(this, _tabletDeviceId, stylusPointerId, timestamp);
if (_stylusDevicesInRange.Count == 0)
{
_stylusDevicesInRange = null; // not needed anymore.
}
}
}
else if (_stylusDevicesInRange != null)
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
// Send event for each StylusDevice being out of range, then clear out the map.
for(int i=0; i < _stylusDevicesInRange.Count; i++)
{
_contexts.OnPenOutOfRange(this, _tabletDeviceId, _stylusDevicesInRange[i], timestamp);
}
_stylusDevicesInRange = null; // nothing in range now.
}
}
/////////////////////////////////////////////////////////////////////
///
/// Critical - Calls SecurityCritical code MS.Win32.Penimc.UnsafeNativeMethods.GetLastSystemEventData
/// and PenContexts.OnSystemEvent. Also handles SecurityCritical data _commHandle.
/// Called by PenThread.FireEvent.
/// TreatAsSafe boundary is PenThread.ThreadProc.
///
[SecurityCritical]
internal void FireSystemGesture(int stylusPointerId, int timestamp)
{
timestamp = EnsureTimestampUnique(timestamp);
_lastInRangeTime = timestamp;
// make sure this gets initialized on the penthread!!
if (_stylusPointDescription == null)
{
InitStylusPointDescription(); // init _stylusPointDescription.
}
int id;
int modifier;
int character;
int stylusMode;
int x, y, buttonState; // (these are not used)
MS.Win32.Penimc.UnsafeNativeMethods.GetLastSystemEventData(
_commHandle.Value,
out id, out modifier, out character,
out x, out y, out stylusMode, out buttonState);
_contexts.OnSystemEvent(
this, _tabletDeviceId, stylusPointerId, timestamp,
(SystemGesture)id, x, y, buttonState);
}
/////////////////////////////////////////////////////////////////////
//
// Make sure timestamp is unique for each event. Note that on each InRange event the
// timestamp _lastInRangeTime is reset to the real event time so we don't have to worry
// about really stale timestamps due to lack of use of a stylus device.
//
private int EnsureTimestampUnique(int timestamp)
{
int delta = unchecked(_lastInRangeTime - timestamp);
// Is last time more current? If so we need to increment and return this.
// NOTE: This deals with wrapping from MaxInt to MinInt.
// Here's some info on how this works...
// int.MaxValue - int.MinValue = -1 (subtracting any negative # from MaxValue keeps this negative)
// int.MinValue - int.MaxValue = 1 (subtracting any positive # from MinValue keeps this positive)
// So as _lastInRangeTime approaches MaxInt if subtracting timestamp is positive then timestamp
// is older and we want to use _lastInRangeTime + 1 to keep the time unique.
// and if _lastInRangeTime is near MinInt then if subtracting timestamp is positive the
// same condition is true in that timestamp is older.
if (delta >= 0)
{
timestamp = unchecked(_lastInRangeTime + 1);
}
return timestamp;
}
// This keeps track of the last time we saw an InRange/OutOfRange event on the pen thread.
internal int LastInRangeTime
{
get { return _lastInRangeTime; }
}
// This returns the count of queued special InRange reports that we use to know if we are
// potentially going inrange.
internal int QueuedInRangeCount
{
get { return _queuedInRangeCount; }
}
// The application uses this to decrement the queued InRange count when it arrives on the app thread.
internal void DecrementQueuedInRangeCount()
{
_queuedInRangeCount--;
}
/////////////////////////////////////////////////////////////////////
///
/// SecurityCritical - This is got under an elevation and is hence critical.
///
internal SecurityCriticalDataClass _pimcContext;
///
/// SecurityCritical - This is got under an elevation and is hence critical.
///
SecurityCriticalData _hwnd;
///
/// SecurityCritical - This is got under an elevation and is hence critical.
///
SecurityCriticalData _commHandle;
///
/// Critical to prevent accidental spread to transparent code
///
[SecurityCritical]
PenContexts _contexts;
///
/// Critical to prevent accidental spread to transparent code
///
[SecurityCritical]
PenThread _penThreadPenContext;
int _id;
int _tabletDeviceId;
StylusPointPropertyInfo _infoX;
StylusPointPropertyInfo _infoY;
bool _supportInRange;
List _stylusDevicesInRange;
bool _isIntegrated;
StylusPointDescription _stylusPointDescription;
int _statusPropertyIndex = -1;
int _lastInRangeTime;
int _queuedInRangeCount;
}
}
// 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
- BitmapPalettes.cs
- HttpApplication.cs
- PrimitiveSchema.cs
- ObjectStateFormatter.cs
- SchemaElement.cs
- GPStream.cs
- RepeatBehaviorConverter.cs
- BaseValidator.cs
- RootBuilder.cs
- OnOperation.cs
- FieldNameLookup.cs
- HandlerElementCollection.cs
- propertytag.cs
- _IPv6Address.cs
- PackageRelationship.cs
- SchemaTableOptionalColumn.cs
- CharAnimationBase.cs
- RootProfilePropertySettingsCollection.cs
- PageCache.cs
- sqlinternaltransaction.cs
- SiteMapSection.cs
- SoapExtension.cs
- InternalDuplexBindingElement.cs
- ThreadStartException.cs
- mediaclock.cs
- IndentedTextWriter.cs
- FontStretches.cs
- JavascriptXmlWriterWrapper.cs
- MemberHolder.cs
- PenContexts.cs
- SafePEFileHandle.cs
- ButtonBase.cs
- TablePattern.cs
- HashAlgorithm.cs
- X509CertificateCollection.cs
- XmlSerializationGeneratedCode.cs
- ByteFacetDescriptionElement.cs
- EllipseGeometry.cs
- ProfessionalColors.cs
- WinEventQueueItem.cs
- DateTimeFormat.cs
- PeerInputChannel.cs
- ConditionalAttribute.cs
- EraserBehavior.cs
- TextCharacters.cs
- CoTaskMemHandle.cs
- LOSFormatter.cs
- SourceLineInfo.cs
- ValidationPropertyAttribute.cs
- WebPart.cs
- Ops.cs
- ExtendedPropertyDescriptor.cs
- AlignmentXValidation.cs
- CommandDevice.cs
- BaseValidator.cs
- SqlDataSourceQueryEditor.cs
- HtmlButton.cs
- PrePrepareMethodAttribute.cs
- InnerItemCollectionView.cs
- ExpressionBinding.cs
- MethodInfo.cs
- ProcessProtocolHandler.cs
- HealthMonitoringSection.cs
- XmlNamespaceMapping.cs
- ToolboxItem.cs
- Base64Stream.cs
- CollectionBuilder.cs
- BitArray.cs
- ExtentKey.cs
- ConfigsHelper.cs
- UnknownWrapper.cs
- X500Name.cs
- QilList.cs
- Rule.cs
- Oid.cs
- XmlSchemaType.cs
- DrawListViewSubItemEventArgs.cs
- RoleManagerSection.cs
- InputBinding.cs
- BCLDebug.cs
- XmlCharacterData.cs
- TextParagraph.cs
- DocumentViewerAutomationPeer.cs
- ResourceManager.cs
- SQLInt64Storage.cs
- InkCanvasAutomationPeer.cs
- PolygonHotSpot.cs
- NavigationHelper.cs
- ValidationResult.cs
- DynamicScriptObject.cs
- FixedDocumentSequencePaginator.cs
- RuntimeArgumentHandle.cs
- PrimitiveType.cs
- QilSortKey.cs
- MetadataPropertyvalue.cs
- MetadataSerializer.cs
- SecurityStateEncoder.cs
- ForEachAction.cs
- MissingMemberException.cs
- CodeVariableReferenceExpression.cs