Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,210 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: ComEventsHelper
**
** Purpose: ComEventHelpers APIs allow binding
** managed delegates to COM's connection point based events.
**
** Date: April 2008
**/
#if FEATURE_COMINTEROP
namespace System.Runtime.InteropServices {
//
// #ComEventsFeature
//
// code:#ComEventsFeature defines two public methods allowing to add/remove .NET delegates handling
// events from COM objects. Those methods are defined as part of code:ComEventsHelper static class
// * code:ComEventsHelper.Combine - will create/reuse-an-existing COM event sink and register the
// specified delegate to be raised when corresponding COM event is raised
// * code:ComEventsHelper.Remove
//
//
// To bind an event handler to the COM object you need to provide the following data:
// * rcw - the instance of the COM object you want to bind to
// * iid - Guid of the source interface you want the sink to implement
// * dispid - dispatch identifier of the event on the source interface you are interested in
// * d - delegate to invoked when corresponding COM event is raised.
//
// #ComEventsArchitecture:
// In COM world, events are handled by so-called event sinks. What these are? COM-based Object Models
// (OMs) define "source" interfaces that need to be implemented by the COM clients to receive events. So,
// event sinks are COM objects implementing a source interfaces. Once an event sink is passed to the COM
// server (through a mechanism known as 'binding/advising to connection point'), COM server will be
// calling source interface methods to "fire events" (advising, connection points, firing events etc. -
// is all COM jargon).
//
// There are few interesting obervations about source interfaces. Usually source interfaces are defined
// as 'dispinterface' - meaning that only late-bound invocations on this interface are allowed. Even
// though it is not illegal to use early bound invocations on source interfaces - the practice is
// discouraged because of versioning concerns.
//
// Notice also that each COM server object might define multiple source interfaces and hence have
// multiple connection points (each CP handles exactly one source interface). COM objects that want to
// fire events are required to implement IConnectionPointContainer interface which is used by the COM
// clients to discovery connection poitns - objects implementing IConnectionPoint interface. Once
// connection point is found - clients can bind to it using IConnectionPoint::Advise (see
// code:ComEventsSink.Advise).
//
// The idea behind code:#ComEventsFeature is to write a "universal event sink" COM component that is
// generic enough to handle all late-bound event firings and invoke corresponding COM delegates (through
// reflection).
//
// When delegate is registered (using code:ComEventsHelper.Combine) we will verify we have corresponding
// event sink created and bound.
//
// But what happens when COM events are fired? code:ComEventsSink.Invoke implements IDispatch::Invoke method
// and this is the entry point that is called. Once our event sink is invoked, we need to find the
// corresponding delegate to invoke . We need to match the dispid of the call that is coming in to a
// dispid of .NET delegate that has been registered for this object. Once this is found we do call the
// delegates using reflection (code:ComEventsMethod.Invoke).
//
// #ComEventsArgsMarshalling
// Notice, that we may not have a delegate registered against every method on the source interface. If we
// were to marshal all the input parameters for methods that do not reach user code - we would end up
// generatic RCWs that are not reachable for user code (the inconvenience it might create is there will
// be RCWs that users can not call Marshal.ReleaseComObject on to explicitly manage the lifetime of these
// COM objects). The above behavior was one of the shortcoimings of legacy TLBIMP's implementation of COM
// event sinking. In our code we will not marshal any data if there is no delegate registered to handle
// the event. (code:ComEventsMethod.Invoke)
//
// #ComEventsFinalization:
// Additional area of interest is when COM sink should be unadvised from the connection point. Legacy
// TLBIMP's implementation of COM event sinks will unadvises the sink when corresponding RCW is GCed.
// This is achieved by rooting the event sinks in a finalizable object stored in RCW's property bag
// (using Marshal.SetComObjectData). Hence, once RCW is no longer reachable - the finalizer is called and
// it would unadvise all the event sinks. We are employing the same strategy here. See storing an
// instance in the RCW at code:ComEventsInfo.FromObject and undadvsing the sinks at
// code:ComEventsInfo.~ComEventsInfo
//
// Classes of interest:
// * code:ComEventsHelpers - defines public methods but there are also a number of internal classes that
// implement the actual COM event sink:
// * code:ComEventsInfo - represents a finalizable container for all event sinks for a particular RCW.
// Lifetime of this instance corresponds to the lifetime of the RCW object
// * code:ComEventsSink - represents a single event sink. Maintains an internal pointer to the next
// instance (in a singly linked list). A collection of code:ComEventsSink is stored at
// code:ComEventsInfo._sinks
// * code:ComEventsMethod - represents a single method from the source interface which has .NET delegates
// attached to it. Maintains an internal pointer to the next instance (in a singly linked list). A
// collection of code:ComEventMethod is stored at code:ComEventsSink._methods
//
// #ComEventsRetValIssue:
// Issue: normally, COM events would not return any value. However, it may happen as described in
// http://support.microsoft.com/kb/810228. Such design might represent a problem for us - e.g. what is
// the return value of a chain of delegates - is it the value of the last call in the chain or the the
// first one? As the above KB article indicates, in cases where OM has events returning values, it is
// suggested that people implement their event sink by explicitly implementing the source interface. This
// means that the problem is already quite complex and we should not be dealing with it - see
// code:ComEventsMethod.Invoke
using System;
using System.Runtime.Remoting;
/// <summary>
/// The static methods provided in ComEventsHelper allow using .NET delegates to subscribe to events
/// raised COM objects.
/// </summary>
public static class ComEventsHelper {
/// <summary>
/// Adds a delegate to the invocation list of events originating from the COM object.
/// </summary>
/// <param name="rcw">COM object firing the events the caller would like to respond to</param>
/// <param name="iid">identifier of the source interface used by COM object to fire events</param>
/// <param name="dispid">dispatch identifier of the method on the source interface</param>
/// <param name="d">delegate to invoke when specifed COM event is fired</param>
[System.Security.SecurityCritical]
public static void Combine(object rcw, Guid iid, int dispid, System.Delegate d) {
rcw = UnwrapIfTransparentProxy(rcw);
lock (rcw) {
ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw);
ComEventsSink sink = eventsInfo.FindSink(ref iid);
if (sink == null) {
sink = eventsInfo.AddSink(ref iid);
}
ComEventsMethod method = sink.FindMethod(dispid);
if (method == null) {
method = sink.AddMethod(dispid);
}
method.AddDelegate(d);
}
}
/// <summary>
/// Removes a delegate from the invocation list of events originating from the COM object.
/// </summary>
/// <param name="rcw">COM object the delegate is attached to</param>
/// <param name="iid">identifier of the source interface used by COM object to fire events</param>
/// <param name="dispid">dispatch identifier of the method on the source interface</param>
/// <param name="d">delegate to remove from the invocation list</param>
/// <returns></returns>
[System.Security.SecurityCritical]
public static Delegate Remove(object rcw, Guid iid, int dispid, System.Delegate d) {
rcw = UnwrapIfTransparentProxy(rcw);
lock (rcw) {
ComEventsInfo eventsInfo = ComEventsInfo.Find(rcw);
if (eventsInfo == null)
return null;
ComEventsSink sink = eventsInfo.FindSink(ref iid);
if (sink == null)
return null;
ComEventsMethod method = sink.FindMethod(dispid);
if (method == null)
return null;
method.RemoveDelegate(d);
if (method.Empty) {
// removed the last event handler for this dispid - need to remove dispid handler
method = sink.RemoveMethod(method);
}
if (method == null) {
// removed last dispid handler for this sink - need to remove the sink
sink = eventsInfo.RemoveSink(sink);
}
if (sink == null) {
// removed last sink for this rcw - need to remove all traces of event info
Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), null);
GC.SuppressFinalize(eventsInfo);
}
return d;
}
}
[System.Security.SecurityCritical]
internal static object UnwrapIfTransparentProxy(object rcw) {
#if FEATURE_REMOTING
if (RemotingServices.IsTransparentProxy(rcw)) {
IntPtr punk = Marshal.GetIUnknownForObject(rcw);
try {
rcw = Marshal.GetObjectForIUnknown(punk);
} finally {
Marshal.Release(punk);
}
}
#endif
return rcw;
}
}
}
#endif

View File

@@ -0,0 +1,100 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: ComEventsInfo
**
** Purpose: part of ComEventHelpers APIs which allow binding
** managed delegates to COM's connection point based events.
**
** Date: April 2008
**/
#if FEATURE_COMINTEROP
namespace System.Runtime.InteropServices {
using System;
using ComTypes = System.Runtime.InteropServices.ComTypes;
// see code:ComEventsHelper#ComEventsArchitecture
[System.Security.SecurityCritical]
internal class ComEventsInfo {
#region fields
private ComEventsSink _sinks;
private object _rcw;
#endregion
#region ctor/dtor
ComEventsInfo(object rcw) {
_rcw = rcw;
}
[System.Security.SecuritySafeCritical]
~ComEventsInfo() {
// see code:ComEventsHelper#ComEventsFinalization
_sinks = ComEventsSink.RemoveAll(_sinks);
}
#endregion
#region static methods
[System.Security.SecurityCritical]
internal static ComEventsInfo Find(object rcw) {
return (ComEventsInfo)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo));
}
// it is caller's responsibility to call this method under lock(rcw)
[System.Security.SecurityCritical]
internal static ComEventsInfo FromObject(object rcw) {
ComEventsInfo eventsInfo = Find(rcw);
if (eventsInfo == null) {
eventsInfo = new ComEventsInfo(rcw);
Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), eventsInfo);
}
return eventsInfo;
}
#endregion
#region internal methods
internal ComEventsSink FindSink(ref Guid iid) {
return ComEventsSink.Find(_sinks, ref iid);
}
// it is caller's responsibility to call this method under lock(rcw)
internal ComEventsSink AddSink(ref Guid iid) {
ComEventsSink sink = new ComEventsSink(_rcw, iid);
_sinks = ComEventsSink.Add(_sinks, sink);
return _sinks;
}
// it is caller's responsibility to call this method under lock(rcw)
[System.Security.SecurityCritical]
internal ComEventsSink RemoveSink(ComEventsSink sink) {
_sinks = ComEventsSink.Remove(_sinks, sink);
return _sinks;
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,253 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: ComEventsMethod
**
** Purpose: part of ComEventHelpers APIs which allow binding
** managed delegates to COM's connection point based events.
**
** Date: April 2008
**/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
#if FEATURE_COMINTEROP
namespace System.Runtime.InteropServices {
// see code:ComEventsHelper#ComEventsArchitecture
internal class ComEventsMethod {
// This delegate wrapper class handles dynamic invocation of delegates. The reason for the wrapper's
// existence is that under certain circumstances we need to coerce arguments to types expected by the
// delegates signature. Normally, reflection (Delegate.DynamicInvoke) handles types coercion
// correctly but one known case is when the expected signature is 'ref Enum' - in this case
// reflection by design does not do the coercion. Since we need to be compatible with COM interop
// handling of this scenario - we are pre-processing delegate's signature by looking for 'ref enums'
// and cache the types required for such coercion.
internal class DelegateWrapper {
private Delegate _d;
private bool _once = false;
private int _expectedParamsCount;
private Type[] _cachedTargetTypes;
public DelegateWrapper(Delegate d) {
_d = d;
}
public Delegate Delegate {
get { return _d; }
set { _d = value; }
}
public object Invoke(object[] args) {
if (_d == null)
return null;
if (_once == false) {
PreProcessSignature();
_once = true;
}
if (_cachedTargetTypes != null && _expectedParamsCount == args.Length) {
for (int i = 0; i < _expectedParamsCount; i++) {
if (_cachedTargetTypes[i] != null) {
args[i] = Enum.ToObject(_cachedTargetTypes[i], args[i]);
}
}
}
return _d.DynamicInvoke(args);
}
private void PreProcessSignature() {
ParameterInfo[] parameters = _d.Method.GetParameters();
_expectedParamsCount = parameters.Length;
Type[] enumTypes = new Type[_expectedParamsCount];
bool needToHandleCoercion = false;
for (int i = 0; i < _expectedParamsCount; i++) {
ParameterInfo pi = parameters[i];
// recognize only 'ref Enum' signatures and cache
// both enum type and the underlying type.
if (pi.ParameterType.IsByRef &&
pi.ParameterType.HasElementType &&
pi.ParameterType.GetElementType().IsEnum) {
needToHandleCoercion = true;
enumTypes[i] = pi.ParameterType.GetElementType();
}
}
if (needToHandleCoercion == true) {
_cachedTargetTypes = enumTypes;
}
}
}
#region private fields
/// <summary>
/// Invoking ComEventsMethod means invoking a multi-cast delegate attached to it.
/// Since multicast delegate's built-in chaining supports only chaining instances of the same type,
/// we need to complement this design by using an explicit linked list data structure.
/// </summary>
private DelegateWrapper [] _delegateWrappers;
private int _dispid;
private ComEventsMethod _next;
#endregion
#region ctor
internal ComEventsMethod(int dispid) {
_delegateWrappers = null;
_dispid = dispid;
}
#endregion
#region static internal methods
internal static ComEventsMethod Find(ComEventsMethod methods, int dispid) {
while (methods != null && methods._dispid != dispid) {
methods = methods._next;
}
return methods;
}
internal static ComEventsMethod Add(ComEventsMethod methods, ComEventsMethod method) {
method._next = methods;
return method;
}
internal static ComEventsMethod Remove(ComEventsMethod methods, ComEventsMethod method) {
if (methods == method) {
methods = methods._next;
} else {
ComEventsMethod current = methods;
while (current != null && current._next != method)
current = current._next;
if (current != null)
current._next = method._next;
}
return methods;
}
#endregion
#region public properties / methods
internal int DispId {
get { return _dispid; }
}
internal bool Empty {
get { return _delegateWrappers == null || _delegateWrappers.Length == 0; }
}
internal void AddDelegate(Delegate d) {
int count = 0;
if (_delegateWrappers != null) {
count = _delegateWrappers.Length;
}
for (int i = 0; i < count; i++) {
if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) {
_delegateWrappers[i].Delegate = Delegate.Combine(_delegateWrappers[i].Delegate, d);
return;
}
}
DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count + 1];
if (count > 0) {
_delegateWrappers.CopyTo(newDelegateWrappers, 0);
}
DelegateWrapper wrapper = new DelegateWrapper(d);
newDelegateWrappers[count] = wrapper;
_delegateWrappers = newDelegateWrappers;
}
internal void RemoveDelegate(Delegate d) {
int count = _delegateWrappers.Length;
int removeIdx = -1;
for (int i = 0; i < count; i++) {
if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) {
removeIdx = i;
break;
}
}
if (removeIdx < 0)
return;
Delegate newDelegate = Delegate.Remove(_delegateWrappers[removeIdx].Delegate, d);
if (newDelegate != null) {
_delegateWrappers[removeIdx].Delegate = newDelegate;
return;
}
// now remove the found entry from the _delegates array
if (count == 1) {
_delegateWrappers = null;
return;
}
DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count - 1];
int j = 0;
while (j < removeIdx) {
newDelegateWrappers[j] = _delegateWrappers[j];
j++;
}
while (j < count-1) {
newDelegateWrappers[j] = _delegateWrappers[j + 1];
j++;
}
_delegateWrappers = newDelegateWrappers;
}
internal object Invoke(object[] args) {
BCLDebug.Assert(Empty == false, "event sink is executed but delegates list is empty");
// Issue: see code:ComEventsHelper#ComEventsRetValIssue
object result = null;
DelegateWrapper[] invocationList = _delegateWrappers;
foreach (DelegateWrapper wrapper in invocationList) {
if (wrapper == null || wrapper.Delegate == null)
continue;
result = wrapper.Invoke(args);
}
return result;
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,293 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: ComEventsSink
**
** Purpose: part of ComEventHelpers APIs which allow binding
** managed delegates to COM's connection point based events.
**
** Date: April 2008
**/
#if FEATURE_COMINTEROP
namespace System.Runtime.InteropServices {
using System;
using System.Diagnostics;
// see code:ComEventsHelper#ComEventsArchitecture
[System.Security.SecurityCritical]
internal class ComEventsSink : NativeMethods.IDispatch, ICustomQueryInterface
{
#region private fields
private Guid _iidSourceItf;
private ComTypes.IConnectionPoint _connectionPoint;
private int _cookie;
private ComEventsMethod _methods;
private ComEventsSink _next;
#endregion
#region ctor
internal ComEventsSink(object rcw, Guid iid) {
_iidSourceItf = iid;
this.Advise(rcw);
}
#endregion
#region static members
internal static ComEventsSink Find(ComEventsSink sinks, ref Guid iid) {
ComEventsSink sink = sinks;
while (sink != null && sink._iidSourceItf != iid) {
sink = sink._next;
}
return sink;
}
internal static ComEventsSink Add(ComEventsSink sinks, ComEventsSink sink) {
sink._next = sinks;
return sink;
}
[System.Security.SecurityCritical]
internal static ComEventsSink RemoveAll(ComEventsSink sinks) {
while (sinks != null) {
sinks.Unadvise();
sinks = sinks._next;
}
return null;
}
[System.Security.SecurityCritical]
internal static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) {
BCLDebug.Assert(sinks != null, "removing event sink from empty sinks collection");
BCLDebug.Assert(sink != null, "specify event sink is null");
if (sink == sinks) {
sinks = sinks._next;
} else {
ComEventsSink current = sinks;
while (current != null && current._next != sink)
current = current._next;
if (current != null) {
current._next = sink._next;
}
}
sink.Unadvise();
return sinks;
}
#endregion
#region public methods
public ComEventsMethod RemoveMethod(ComEventsMethod method) {
_methods = ComEventsMethod.Remove(_methods, method);
return _methods;
}
public ComEventsMethod FindMethod(int dispid) {
return ComEventsMethod.Find(_methods, dispid);
}
public ComEventsMethod AddMethod(int dispid) {
ComEventsMethod method = new ComEventsMethod(dispid);
_methods = ComEventsMethod.Add(_methods, method);
return method;
}
#endregion
#region IDispatch Members
[System.Security.SecurityCritical]
void NativeMethods.IDispatch.GetTypeInfoCount(out uint pctinfo) {
pctinfo = 0;
}
[System.Security.SecurityCritical]
void NativeMethods.IDispatch.GetTypeInfo(uint iTInfo, int lcid, out IntPtr info) {
throw new NotImplementedException();
}
[System.Security.SecurityCritical]
void NativeMethods.IDispatch.GetIDsOfNames(ref Guid iid, string[] names, uint cNames, int lcid, int[] rgDispId) {
throw new NotImplementedException();
}
private const VarEnum VT_BYREF_VARIANT = VarEnum.VT_BYREF | VarEnum.VT_VARIANT;
private const VarEnum VT_TYPEMASK = (VarEnum) 0x0fff;
private const VarEnum VT_BYREF_TYPEMASK = VT_TYPEMASK | VarEnum.VT_BYREF;
private static unsafe Variant *GetVariant(Variant *pSrc)
{
if (pSrc->VariantType == VT_BYREF_VARIANT)
{
// For VB6 compatibility reasons, if the VARIANT is a VT_BYREF | VT_VARIANT that
// contains another VARIANT with VT_BYREF | VT_VARIANT, then we need to extract the
// inner VARIANT and use it instead of the outer one. Note that if the inner VARIANT
// is VT_BYREF | VT_VARIANT | VT_ARRAY, it will pass the below test too.
Variant *pByRefVariant = (Variant *)pSrc->AsByRefVariant;
if ((pByRefVariant->VariantType & VT_BYREF_TYPEMASK) == VT_BYREF_VARIANT)
return (Variant *)pByRefVariant;
}
return pSrc;
}
[System.Security.SecurityCritical]
unsafe void NativeMethods.IDispatch.Invoke(
int dispid,
ref Guid riid,
int lcid,
ComTypes.INVOKEKIND wFlags,
ref ComTypes.DISPPARAMS pDispParams,
IntPtr pvarResult,
IntPtr pExcepInfo,
IntPtr puArgErr) {
ComEventsMethod method = FindMethod(dispid);
if (method == null)
return;
// notice the unsafe pointers we are using. This is to avoid unnecessary
// arguments marshalling. see code:ComEventsHelper#ComEventsArgsMarshalling
object [] args = new object[pDispParams.cArgs];
int [] byrefsMap = new int[pDispParams.cArgs];
bool [] usedArgs = new bool[pDispParams.cArgs];
Variant* pvars = (Variant*)pDispParams.rgvarg;
int* pNamedArgs = (int*)pDispParams.rgdispidNamedArgs;
// copy the named args (positional) as specified
int i;
int pos;
for (i = 0; i < pDispParams.cNamedArgs; i++) {
pos = pNamedArgs[i];
Variant* pvar = GetVariant(&pvars[i]);
args[pos] = pvar->ToObject();
usedArgs[pos] = true;
if (pvar->IsByRef) {
byrefsMap[pos] = i;
} else {
byrefsMap[pos] = -1;
}
}
// copy the rest of the arguments in the reverse order
pos = 0;
for (; i < pDispParams.cArgs; i++) {
// find the next unassigned argument
while (usedArgs[pos]) {
++pos;
}
Variant* pvar = GetVariant(&pvars[pDispParams.cArgs - 1 - i]);
args[pos] = pvar->ToObject();
if (pvar->IsByRef)
byrefsMap[pos] = pDispParams.cArgs - 1 - i;
else
byrefsMap[pos] = -1;
pos++;
}
// Do the actual delegate invocation
object result;
result = method.Invoke(args);
// convert result to VARIANT
if (pvarResult != IntPtr.Zero) {
Marshal.GetNativeVariantForObject(result, pvarResult);
}
// Now we need to marshal all the byrefs back
for (i = 0; i < pDispParams.cArgs; i++) {
int idxToPos = byrefsMap[i];
if (idxToPos == -1)
continue;
GetVariant(&pvars[idxToPos])->CopyFromIndirect(args[i]);
}
}
#endregion
static Guid IID_IManagedObject = new Guid("{C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4}");
[System.Security.SecurityCritical]
CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv) {
ppv = IntPtr.Zero;
if (iid == this._iidSourceItf || iid == typeof(NativeMethods.IDispatch).GUID) {
ppv = Marshal.GetComInterfaceForObject(this, typeof(NativeMethods.IDispatch), CustomQueryInterfaceMode.Ignore);
return CustomQueryInterfaceResult.Handled;
}
else if (iid == IID_IManagedObject)
{
return CustomQueryInterfaceResult.Failed;
}
return CustomQueryInterfaceResult.NotHandled;
}
#region private methods
private void Advise(object rcw) {
BCLDebug.Assert(_connectionPoint == null, "comevent sink is already advised");
ComTypes.IConnectionPointContainer cpc = (ComTypes.IConnectionPointContainer)rcw;
ComTypes.IConnectionPoint cp;
cpc.FindConnectionPoint(ref _iidSourceItf, out cp);
object sinkObject = this;
cp.Advise(sinkObject, out _cookie);
_connectionPoint = cp;
}
[System.Security.SecurityCritical]
private void Unadvise() {
BCLDebug.Assert(_connectionPoint != null, "can not unadvise from empty connection point");
try {
_connectionPoint.Unadvise(_cookie);
Marshal.ReleaseComObject(_connectionPoint);
} catch (System.Exception) {
// swallow all exceptions on unadvise
// the host may not be available at this point
} finally {
_connectionPoint = null;
}
}
#endregion
};
}
#endif

View File

@@ -0,0 +1,47 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IBindCtx
**
**
** Purpose: IBindCtx interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[StructLayout(LayoutKind.Sequential)]
public struct BIND_OPTS
{
public int cbStruct;
public int grfFlags;
public int grfMode;
public int dwTickCountDeadline;
}
[Guid("0000000e-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IBindCtx
{
void RegisterObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
void RevokeObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
void ReleaseBoundObjects();
void SetBindOptions([In()] ref BIND_OPTS pbindopts);
void GetBindOptions(ref BIND_OPTS pbindopts);
void GetRunningObjectTable(out IRunningObjectTable pprot);
void RegisterObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] Object punk);
void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] out Object ppunk);
void EnumObjectParam(out IEnumString ppenum);
[PreserveSig]
int RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey);
}
}

View File

@@ -0,0 +1,31 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IConnectionPoint
**
**
** Purpose: IConnectionPoint interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("B196B286-BAB4-101A-B69C-00AA00341D07")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IConnectionPoint
{
void GetConnectionInterface(out Guid pIID);
void GetConnectionPointContainer(out IConnectionPointContainer ppCPC);
void Advise([MarshalAs(UnmanagedType.Interface)] Object pUnkSink, out int pdwCookie);
void Unadvise(int dwCookie);
void EnumConnections(out IEnumConnections ppEnum);
}
}

View File

@@ -0,0 +1,28 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IConnectionPointContainer
**
**
** Purpose: IConnectionPointContainer interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("B196B284-BAB4-101A-B69C-00AA00341D07")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IConnectionPointContainer
{
void EnumConnectionPoints(out IEnumConnectionPoints ppEnum);
void FindConnectionPoint([In] ref Guid riid, out IConnectionPoint ppCP);
}
}

View File

@@ -0,0 +1,32 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IEnumConnectionPoints
**
**
** Purpose: IEnumConnectionPoints interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("B196B285-BAB4-101A-B69C-00AA00341D07")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumConnectionPoints
{
[PreserveSig]
int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IConnectionPoint[] rgelt, IntPtr pceltFetched);
[PreserveSig]
int Skip(int celt);
void Reset();
void Clone(out IEnumConnectionPoints ppenum);
}
}

View File

@@ -0,0 +1,41 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IEnumConnections
**
**
** Purpose: IEnumConnections interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CONNECTDATA
{
[MarshalAs(UnmanagedType.Interface)]
public Object pUnk;
public int dwCookie;
}
[Guid("B196B287-BAB4-101A-B69C-00AA00341D07")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumConnections
{
[PreserveSig]
int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] CONNECTDATA[] rgelt, IntPtr pceltFetched);
[PreserveSig]
int Skip(int celt);
void Reset();
void Clone(out IEnumConnections ppenum);
}
}

View File

@@ -0,0 +1,29 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==========================================================================
**
** Interface: IEnumerable
**
**
** Purpose:
** This interface is redefined here since the original IEnumerable interface
** has all its methods marked as ecall's since it is a managed standard
** interface. This interface is used from within the runtime to make a call
** on the COM server directly when it implements the IEnumerable interface.
**
**
==========================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
internal interface IEnumerable
{
[DispId(-4)]
System.Collections.IEnumerator GetEnumerator();
}
}

View File

@@ -0,0 +1,35 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==========================================================================
**
** Interface: IEnumerator
**
**
** Purpose:
** This interface is redefined here since the original IEnumerator interface
** has all its methods marked as ecall's since it is a managed standard
** interface. This interface is used from within the runtime to make a call
** on the COM server directly when it implements the IEnumerator interface.
**
**
==========================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
internal interface IEnumerator
{
bool MoveNext();
Object Current
{
get;
}
void Reset();
}
}

View File

@@ -0,0 +1,32 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IEnumMoniker
**
**
** Purpose: IEnumMoniker interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("00000102-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumMoniker
{
[PreserveSig]
int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IMoniker[] rgelt, IntPtr pceltFetched);
[PreserveSig]
int Skip(int celt);
void Reset();
void Clone(out IEnumMoniker ppenum);
}
}

View File

@@ -0,0 +1,32 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IEnumString
**
**
** Purpose: IEnumString interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("00000101-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumString
{
[PreserveSig]
int Next(int celt, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0), Out] String[] rgelt, IntPtr pceltFetched);
[PreserveSig]
int Skip(int celt);
void Reset();
void Clone(out IEnumString ppenum);
}
}

View File

@@ -0,0 +1,36 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IEnumVARIANT
**
**
** Purpose: IEnumVARIANT interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("00020404-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumVARIANT
{
[PreserveSig]
int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0), Out] object[] rgVar, IntPtr pceltFetched);
[PreserveSig]
int Skip(int celt);
[PreserveSig]
int Reset();
IEnumVARIANT Clone();
}
}

View File

@@ -0,0 +1,32 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==========================================================================
**
** Interface: IExpando
**
**
** Purpose:
** This interface is redefined here since the original IExpando interface
** has all its methods marked as ecall's since it is a managed standard
** interface. This interface is used from within the runtime to make a call
** on the COM server directly when it implements the IExpando interface.
**
**
==========================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
using System.Reflection;
[Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")]
internal interface IExpando : IReflect
{
FieldInfo AddField(String name);
PropertyInfo AddProperty(String name);
MethodInfo AddMethod(String name, Delegate method);
void RemoveMember(MemberInfo m);
}
}

View File

@@ -0,0 +1,63 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IMoniker
**
**
** Purpose: IMoniker interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public int dwLowDateTime;
public int dwHighDateTime;
}
[Guid("0000000f-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IMoniker
{
// IPersist portion
void GetClassID(out Guid pClassID);
// IPersistStream portion
[PreserveSig]
int IsDirty();
void Load(IStream pStm);
void Save(IStream pStm, [MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
void GetSizeMax(out Int64 pcbSize);
// IMoniker portion
void BindToObject(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
void BindToStorage(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out Object ppvObj);
void Reduce(IBindCtx pbc, int dwReduceHowFar, ref IMoniker ppmkToLeft, out IMoniker ppmkReduced);
void ComposeWith(IMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker ppmkComposite);
void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker ppenumMoniker);
[PreserveSig]
int IsEqual(IMoniker pmkOtherMoniker);
void Hash(out int pdwHash);
[PreserveSig]
int IsRunning(IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning);
void GetTimeOfLastChange(IBindCtx pbc, IMoniker pmkToLeft, out FILETIME pFileTime);
void Inverse(out IMoniker ppmk);
void CommonPrefixWith(IMoniker pmkOther, out IMoniker ppmkPrefix);
void RelativePathTo(IMoniker pmkOther, out IMoniker ppmkRelPath);
void GetDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out String ppszDisplayName);
void ParseDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] String pszDisplayName, out int pchEaten, out IMoniker ppmkOut);
[PreserveSig]
int IsSystemMoniker(out int pdwMksys);
}
}

View File

@@ -0,0 +1,36 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IPersistFile
**
**
** Purpose: IPersistFile interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("0000010b-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IPersistFile
{
// IPersist portion
void GetClassID(out Guid pClassID);
// IPersistFile portion
[PreserveSig]
int IsDirty();
void Load([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, int dwMode);
void Save([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember);
void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] String pszFileName);
void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out String ppszFileName);
}
}

View File

@@ -0,0 +1,80 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==========================================================================
**
** Interface: IReflect
**
**
** Purpose:
** This interface is redefined here since the original IReflect interface
** has all its methods marked as ecall's since it is a managed standard
** interface. This interface is used from within the runtime to make a call
** on the COM server directly when it implements the IReflect interface.
**
**
==========================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
using System.Reflection;
using CultureInfo = System.Globalization.CultureInfo;
[Guid("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")]
internal interface IReflect
{
MethodInfo GetMethod(String name,BindingFlags bindingAttr,Binder binder,
Type[] types,ParameterModifier[] modifiers);
MethodInfo GetMethod(String name,BindingFlags bindingAttr);
MethodInfo[] GetMethods(
BindingFlags bindingAttr);
FieldInfo GetField(
String name,
BindingFlags bindingAttr);
FieldInfo[] GetFields(
BindingFlags bindingAttr);
PropertyInfo GetProperty(
String name,
BindingFlags bindingAttr);
PropertyInfo GetProperty(
String name,
BindingFlags bindingAttr,
Binder binder,
Type returnType,
Type[] types,
ParameterModifier[] modifiers);
PropertyInfo[] GetProperties(
BindingFlags bindingAttr);
MemberInfo[] GetMember(
String name,
BindingFlags bindingAttr);
MemberInfo[] GetMembers(
BindingFlags bindingAttr);
Object InvokeMember(
String name,
BindingFlags invokeAttr,
Binder binder,
Object target,
Object[] args,
ParameterModifier[] modifiers,
CultureInfo culture,
String[] namedParameters);
Type UnderlyingSystemType
{
get;
}
}
}

View File

@@ -0,0 +1,36 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IRunningObjectTable
**
**
** Purpose: IRunningObjectTable interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[Guid("00000010-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IRunningObjectTable
{
int Register(int grfFlags, [MarshalAs(UnmanagedType.Interface)] Object punkObject, IMoniker pmkObjectName);
void Revoke(int dwRegister);
[PreserveSig]
int IsRunning(IMoniker pmkObjectName);
[PreserveSig]
int GetObject(IMoniker pmkObjectName, [MarshalAs(UnmanagedType.Interface)] out Object ppunkObject);
void NoteChangeTime(int dwRegister, ref FILETIME pfiletime);
[PreserveSig]
int GetTimeOfLastChange(IMoniker pmkObjectName, out FILETIME pfiletime);
void EnumRunning(out IEnumMoniker ppenumMoniker);
}
}

View File

@@ -0,0 +1,57 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=============================================================================
**
** Class: IStream
**
**
** Purpose: IStream interface definition.
**
**
=============================================================================*/
namespace System.Runtime.InteropServices.ComTypes
{
using System;
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct STATSTG
{
public String pwcsName;
public int type;
public Int64 cbSize;
public FILETIME mtime;
public FILETIME ctime;
public FILETIME atime;
public int grfMode;
public int grfLocksSupported;
public Guid clsid;
public int grfStateBits;
public int reserved;
}
[Guid("0000000c-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IStream
{
// ISequentialStream portion
void Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] Byte[] pv, int cb, IntPtr pcbRead);
void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] pv, int cb, IntPtr pcbWritten);
// IStream portion
void Seek(Int64 dlibMove, int dwOrigin, IntPtr plibNewPosition);
void SetSize(Int64 libNewSize);
void CopyTo(IStream pstm, Int64 cb, IntPtr pcbRead, IntPtr pcbWritten);
void Commit(int grfCommitFlags);
void Revert();
void LockRegion(Int64 libOffset, Int64 cb, int dwLockType);
void UnlockRegion(Int64 libOffset, Int64 cb, int dwLockType);
void Stat(out STATSTG pstatstg, int grfStatFlag);
void Clone(out IStream ppstm);
}
}

Some files were not shown because too many files have changed in this diff Show More