Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / ComponentModel / COM2Interop / COM2Properties.cs / 1 / COM2Properties.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Windows.Forms.ComponentModel.Com2Interop {
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Win32;
///
///
/// This class is responsible for managing a set or properties for a native object. It determines
/// when the properties need to be refreshed, and owns the extended handlers for those properties.
///
internal class Com2Properties {
private static TraceSwitch DbgCom2PropertiesSwitch = new TraceSwitch("DbgCom2Properties", "Com2Properties: debug Com2 properties manager");
///
///
/// This is the interval that we'll hold props for. If someone doesn't touch an object
/// for this amount of time, we'll dump the properties from our cache.
///
/// 5 minutes -- ticks are 1/10,000,000th of a second
///
private static long AGE_THRESHHOLD = (long)(10000000L * 60L * 5L);
///
///
/// This is the object that gave us the properties. We hold a WeakRef so we don't addref the object.
///
internal WeakReference weakObjRef;
///
///
/// This is our list of properties.
///
private Com2PropertyDescriptor[] props;
///
///
/// The index of the default property
///
private int defaultIndex = -1;
///
///
/// The timestamp of the last operation on this property manager, usually
/// when the property list was fetched.
///
private long touchedTime;
///
/// For non-IProvideMultipleClassInfo ITypeInfos, this is the version number on the last
/// ITypeInfo we looked at. If this changes, we know we need to dump the cache.
///
private long[] typeInfoVersions;
#if DEBUG
private string dbgObjName;
private string dbgObjClass;
#endif
private int alwaysValid = 0;
///
///
/// These are the interfaces we recognize for extended browsing.
///
private static Type[] extendedInterfaces = new Type[]{
typeof(NativeMethods.ICategorizeProperties),
typeof(NativeMethods.IProvidePropertyBuilder),
typeof(NativeMethods.IPerPropertyBrowsing),
typeof(NativeMethods.IVsPerPropertyBrowsing),
typeof(NativeMethods.IManagedPerPropertyBrowsing)};
///
///
/// These are the classes of handlers corresponding to the extended
/// interfaces above.
///
private static Type[] extendedInterfaceHandlerTypes = new Type[]{
typeof(Com2ICategorizePropertiesHandler),
typeof(Com2IProvidePropertyBuilderHandler),
typeof(Com2IPerPropertyBrowsingHandler),
typeof(Com2IVsPerPropertyBrowsingHandler),
typeof(Com2IManagedPerPropertyBrowsingHandler)};
public event EventHandler Disposed;
///
///
/// Default ctor.
///
public Com2Properties(object obj, Com2PropertyDescriptor[] props, int defaultIndex) {
#if DEBUG
ComNativeDescriptor cnd = new ComNativeDescriptor();
this.dbgObjName = cnd.GetName(obj);
if (this.dbgObjName == null) {
this.dbgObjName = "(null)";
}
this.dbgObjClass = cnd.GetClassName(obj);
if (this.dbgObjClass == null) {
this.dbgObjClass = "(null)";
}
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Creating Com2Properties for object " + dbgObjName + ", class=" + dbgObjClass);
#endif
// set up our variables
SetProps(props);
weakObjRef = new WeakReference(obj);
this.defaultIndex = defaultIndex;
typeInfoVersions = GetTypeInfoVersions(obj);
touchedTime = DateTime.Now.Ticks;
}
internal bool AlwaysValid {
get {
return this.alwaysValid > 0;
}
set {
if (value) {
if (alwaysValid == 0 && !CheckValid()) {
return;
}
this.alwaysValid++;
}
else {
if (alwaysValid > 0) {
this.alwaysValid--;
}
}
}
}
///
///
/// Retrieve the default property.
///
public Com2PropertyDescriptor DefaultProperty{
get{
if (!CheckValid(true)) {
return null;
}
if (defaultIndex == -1) {
if (props.Length > 0) {
return props[0];
}
else {
return null;
}
}
Debug.Assert(defaultIndex < props.Length, "Whoops! default index is > props.Length");
return props[defaultIndex];
}
}
///
///
/// The object that created the list of properties. This will
/// return null if the timeout has passed or the ref has died.
///
public object TargetObject{
get{
if (!CheckValid(false) || touchedTime == 0) {
#if DEBUG
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("CheckValid called on dead object!");
#endif
return null;
}
return weakObjRef.Target;
}
}
///
///
/// How long since these props have been queried.
///
public long TicksSinceTouched{
get{
if (touchedTime == 0) {
return 0;
}
return DateTime.Now.Ticks - touchedTime;
}
}
///
///
/// Returns the list of properties
///
public Com2PropertyDescriptor[] Properties{
get{
CheckValid(true);
if (touchedTime == 0 || props == null) {
return null;
}
touchedTime = DateTime.Now.Ticks;
// refresh everyone!
for (int i = 0; i < props.Length; i++) {
props[i].SetNeedsRefresh(Com2PropertyDescriptorRefresh.All, true);
}
#if DEBUG
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Returning prop array for object " + dbgObjName + ", class=" + dbgObjClass);
#endif
return props;
}
}
///
///
/// Should this guy be refreshed because of old age?
///
public bool TooOld{
get{
CheckValid(false);
if (touchedTime == 0) {
return false;
}
return TicksSinceTouched > AGE_THRESHHOLD;
}
}
///
///
/// Checks the source object for eache extended browsing inteface
/// listed in extendedInterfaces and creates a handler from extendedInterfaceHandlerTypes
/// to handle it.
///
public void AddExtendedBrowsingHandlers(Hashtable handlers) {
object target = this.TargetObject;
if (target == null) {
return;
}
// process all our registered types
Type t;
for (int i = 0; i < extendedInterfaces.Length; i++) {
t = extendedInterfaces[i];
// is this object an implementor of the interface?
//
if (t.IsInstanceOfType(target)) {
// since handlers must be stateless, check to see if we've already
// created one of this type
//
Com2ExtendedBrowsingHandler handler = (Com2ExtendedBrowsingHandler)handlers[t];
if (handler == null) {
handler = (Com2ExtendedBrowsingHandler)Activator.CreateInstance(extendedInterfaceHandlerTypes[i]);
handlers[t] = handler;
}
// make sure we got the right one
//
if (t.IsAssignableFrom(handler.Interface)) {
#if DEBUG
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Adding browsing handler type " + handler.Interface.Name + " to object " + dbgObjName + ", class=" + dbgObjClass);
#endif
// allow the handler to attach itself to the appropriate properties
//
handler.SetupPropertyHandlers(props);
}
else {
throw new ArgumentException(SR.GetString(SR.COM2BadHandlerType, t.Name, handler.Interface.Name));
}
}
}
}
public void Dispose() {
#if DEBUG
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Disposing property manager for " + dbgObjName + ", class=" + dbgObjClass);
#endif
if (props != null) {
if (Disposed != null) {
Disposed(this, EventArgs.Empty);
}
weakObjRef = null;
props = null;
touchedTime = 0;
}
}
public bool CheckValid() {
return CheckValid(false);
}
///
///
/// Make sure this property list is still valid.
///
/// 1) WeakRef is still alive
/// 2) Our timeout hasn't passed
///
public bool CheckValid(bool checkVersions) {
if (this.AlwaysValid) {
return true;
}
bool valid = weakObjRef != null && weakObjRef.IsAlive;
// check the version information for each ITypeInfo the object exposes.
//
if (valid && checkVersions) {
//
long[] newTypeInfoVersions = GetTypeInfoVersions(weakObjRef.Target);
if (newTypeInfoVersions.Length != typeInfoVersions.Length) {
valid = false;
} else {
// compare each version number to the old one.
//
for (int i = 0; i < newTypeInfoVersions.Length; i++) {
if (newTypeInfoVersions[i] != typeInfoVersions[i]) {
valid = false;
break;
}
}
}
if (!valid) {
// update to the new version list we have.
//
typeInfoVersions = newTypeInfoVersions;
}
}
if (!valid) {
// weak ref has died, so remove this from the hash table
//
#if DEBUG
if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Disposing reference to object " + dbgObjName + ", class=" + dbgObjClass + " (weakRef " + (weakObjRef == null ? "null" : "dead") + ")");
#endif
Dispose();
}
return valid;
}
///
/// Gets a list of version longs for each type info in the COM object
/// representing hte current version stamp, function and variable count.
/// If any of these things change, we'll re-fetch the properties.
///
private long[] GetTypeInfoVersions(object comObject) {
// get type infos
//
UnsafeNativeMethods.ITypeInfo[] pTypeInfos = Com2TypeInfoProcessor.FindTypeInfos(comObject, false);
// build up the info.
//
long[] versions = new long[pTypeInfos.Length];
for (int i = 0; i < pTypeInfos.Length; i++) {
versions [i] = GetTypeInfoVersion(pTypeInfos[i]);
}
return versions;
}
private static int countOffset = -1;
private static int versionOffset = -1;
// we define a struct here so we can use unsafe code to marshal it
// as a blob of memory. This is here as a reference to how big and where the members are.
//
/*private struct tagTYPEATTR {
public Guid guid; //16
public int lcid; // 4
public int dwReserved; // 4
public int memidConstructor; // 4
public int memidDestructor; // 4
public IntPtr lpstrSchema; // platform
public int cbSizeInstance; // 4
public int typekind; // 4
public short cFuncs; // 2
public short cVars; // 2
public short cImplTypes; // 2
public short cbSizeVft; // 2
public short cbAlignment; // 2
public short wTypeFlags; // 2
public short wMajorVerNum; // 2
public short wMinorVerNum; // 2
public int tdescAlias_unionMember;
public short tdescAlias_vt;
public int idldescType_dwReserved;
public short idldescType_wIDLFlags;
}*/
// the offset of the cFunc member in the TYPEATTR structure.
//
private static int CountMemberOffset {
get {
if (countOffset == -1) {
countOffset = Marshal.SizeOf(typeof(Guid)) + IntPtr.Size + 24;
}
return countOffset;
}
}
// the offset of the cMajorVerNum member in the TYPEATTR structure.
//
private static int VersionOffset {
get {
if (versionOffset == -1) {
versionOffset = CountMemberOffset + 12;
}
return versionOffset;
}
}
private unsafe long GetTypeInfoVersion(UnsafeNativeMethods.ITypeInfo pTypeInfo) {
IntPtr pTypeAttr = IntPtr.Zero;
int hr = pTypeInfo.GetTypeAttr(ref pTypeAttr);
if (!NativeMethods.Succeeded(hr)) {
return 0;
}
System.Runtime.InteropServices.ComTypes.TYPEATTR pTAStruct;
try {
try {
// just access directly...no marshalling needed!
//
pTAStruct = *(System.Runtime.InteropServices.ComTypes.TYPEATTR*)pTypeAttr;
}
catch {
return 0;
}
long result = 0;
// we pull two things out of the struct: the
// number of functions and variables, and the version.
// since they are next to each other, we just pull the memory directly.
//
// the cFuncs and cVars are both shorts, so we read them as one block of ints.
//
//
int* pResult = (int*)&result;
byte* pbStruct = (byte*)&pTAStruct;
// in the low byte, pull the number of props.
//
*pResult = *(int*)(pbStruct + CountMemberOffset);
// move up to the high word of the long.
//
pResult++;
// now pull out the version info.
//
*pResult = *(int*)(pbStruct + VersionOffset);
// return that composite long.
//
return result;
}
finally {
pTypeInfo.ReleaseTypeAttr(pTypeAttr);
}
}
///
///
/// Set the props for this object, and notify each property
/// that we are now it's manager
///
internal void SetProps(Com2PropertyDescriptor[] props) {
this.props = props;
if (props != null) {
for (int i = 0; i < props.Length; i++) {
props[i].PropertyManager = this;
}
}
}
}
}
// 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
- HttpHeaderCollection.cs
- RadioButtonList.cs
- VolatileResourceManager.cs
- PersonalizationEntry.cs
- CustomAttributeBuilder.cs
- MailHeaderInfo.cs
- WhereQueryOperator.cs
- LogicalExpr.cs
- QueryOpcode.cs
- SystemUdpStatistics.cs
- AssemblyContextControlItem.cs
- Normalization.cs
- OleDbErrorCollection.cs
- TextEditorSpelling.cs
- DeadCharTextComposition.cs
- MissingMemberException.cs
- Ipv6Element.cs
- TranslateTransform3D.cs
- DataTemplateKey.cs
- entitydatasourceentitysetnameconverter.cs
- HttpCookie.cs
- UnmanagedMemoryStreamWrapper.cs
- CacheSection.cs
- XmlAnyAttributeAttribute.cs
- ListViewCommandEventArgs.cs
- CustomTypeDescriptor.cs
- DictionaryTraceRecord.cs
- BCryptSafeHandles.cs
- UnsettableComboBox.cs
- RootNamespaceAttribute.cs
- CustomErrorsSectionWrapper.cs
- ComponentCommands.cs
- ErrorBehavior.cs
- ElementNotEnabledException.cs
- Visual3D.cs
- TypeNameConverter.cs
- InvalidCastException.cs
- LockCookie.cs
- PropertyGroupDescription.cs
- EntityWrapper.cs
- FillBehavior.cs
- ResourceKey.cs
- ExtendedProperty.cs
- NativeCompoundFileAPIs.cs
- DbProviderConfigurationHandler.cs
- DBConnection.cs
- ResourceSet.cs
- ScriptResourceInfo.cs
- ToolboxControl.cs
- MailDefinition.cs
- MessageProtectionOrder.cs
- Decoder.cs
- RowUpdatedEventArgs.cs
- TransformerInfo.cs
- IFlowDocumentViewer.cs
- DefaultPrintController.cs
- DataSetUtil.cs
- DataErrorValidationRule.cs
- RedBlackList.cs
- EventRouteFactory.cs
- TextTreeDeleteContentUndoUnit.cs
- SelectionEditingBehavior.cs
- BinaryNegotiation.cs
- AudioFileOut.cs
- StreamedWorkflowDefinitionContext.cs
- XomlCompilerError.cs
- SystemWebCachingSectionGroup.cs
- GlobalEventManager.cs
- ExpressionLexer.cs
- NetCodeGroup.cs
- srgsitem.cs
- ComponentCollection.cs
- AssociationSetMetadata.cs
- WebPartManager.cs
- ItemContainerPattern.cs
- LocatorManager.cs
- SurrogateEncoder.cs
- ExtractorMetadata.cs
- RegexReplacement.cs
- GCHandleCookieTable.cs
- DoubleAnimation.cs
- CredentialCache.cs
- ProtocolsSection.cs
- ConfigXmlText.cs
- Primitive.cs
- IIS7WorkerRequest.cs
- AvTraceFormat.cs
- CriticalExceptions.cs
- CopyAction.cs
- BuildProviderAppliesToAttribute.cs
- TextContainer.cs
- UrlUtility.cs
- SQLGuidStorage.cs
- HasActivatableWorkflowEvent.cs
- RadioButtonAutomationPeer.cs
- EventLogPermissionEntry.cs
- Imaging.cs
- Rotation3D.cs
- XmlTextAttribute.cs
- Int32CollectionValueSerializer.cs