Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / InteropServices / ComEventsSink.cs / 1305376 / ComEventsSink.cs
// ==++== // // 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(); } [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]; args[pos] = pvars[i].ToObject(); usedArgs[pos] = true; if (pvars[i].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 = &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; 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 // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // 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(); } [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]; args[pos] = pvars[i].ToObject(); usedArgs[pos] = true; if (pvars[i].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 = &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; 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 // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HandlerBase.cs
- DrawingBrush.cs
- _BaseOverlappedAsyncResult.cs
- XmlSecureResolver.cs
- CroppedBitmap.cs
- EventHandlersStore.cs
- StreamingContext.cs
- ProfileModule.cs
- PreviousTrackingServiceAttribute.cs
- Select.cs
- ThemeDirectoryCompiler.cs
- WorkflowHostingEndpoint.cs
- URIFormatException.cs
- Int32Converter.cs
- Span.cs
- MessagePropertyFilter.cs
- Regex.cs
- HandleCollector.cs
- ErasingStroke.cs
- XPathException.cs
- AutomationEventArgs.cs
- PseudoWebRequest.cs
- shaper.cs
- HtmlTernaryTree.cs
- WebPartZone.cs
- ItemsChangedEventArgs.cs
- JsonEncodingStreamWrapper.cs
- VectorAnimation.cs
- ConsoleTraceListener.cs
- FileLevelControlBuilderAttribute.cs
- FrugalList.cs
- DataControlImageButton.cs
- Table.cs
- ContractUtils.cs
- DBDataPermissionAttribute.cs
- codemethodreferenceexpression.cs
- Evidence.cs
- SecureStringHasher.cs
- Typography.cs
- ReachUIElementCollectionSerializer.cs
- ExtensionElement.cs
- SqlDependency.cs
- StatusBarItemAutomationPeer.cs
- PropertyEmitterBase.cs
- ToolStripItemImageRenderEventArgs.cs
- DesignerLoader.cs
- UnsafeNativeMethods.cs
- TextTreeNode.cs
- WebDisplayNameAttribute.cs
- ICspAsymmetricAlgorithm.cs
- DataGridViewHeaderCell.cs
- LayoutTableCell.cs
- ContainerSelectorActiveEvent.cs
- ActiveDocumentEvent.cs
- IsolatedStorage.cs
- UIElementAutomationPeer.cs
- GenerateScriptTypeAttribute.cs
- TagMapInfo.cs
- ObjectFullSpanRewriter.cs
- MissingFieldException.cs
- EnumValAlphaComparer.cs
- CodeGeneratorOptions.cs
- FileLevelControlBuilderAttribute.cs
- LoginViewDesigner.cs
- Int16KeyFrameCollection.cs
- CodeCompiler.cs
- BitmapSizeOptions.cs
- StructuredTypeEmitter.cs
- CheckBoxField.cs
- TextAnchor.cs
- Effect.cs
- HttpRuntime.cs
- XmlWriterTraceListener.cs
- SamlAssertionDirectKeyIdentifierClause.cs
- DiscoveryDocumentSerializer.cs
- LinkArea.cs
- XmlComplianceUtil.cs
- InvalidAsynchronousStateException.cs
- SplitterPanel.cs
- FixedSOMFixedBlock.cs
- TcpServerChannel.cs
- TextEditorCharacters.cs
- XmlSchemaImport.cs
- PermissionToken.cs
- TimeZone.cs
- EventLogPermissionAttribute.cs
- HtmlInputPassword.cs
- ToolStrip.cs
- WorkflowQueueInfo.cs
- DataGridViewHitTestInfo.cs
- WindowsStreamSecurityBindingElement.cs
- RawStylusSystemGestureInputReport.cs
- CompiledRegexRunner.cs
- Propagator.cs
- documentsequencetextpointer.cs
- Transform.cs
- ConnectionPointConverter.cs
- DataObjectMethodAttribute.cs
- StringConcat.cs
- RefreshResponseInfo.cs