ContactManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / SystemNet / Net / PeerToPeer / Collaboration / ContactManager.cs / 1305376 / ContactManager.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net.PeerToPeer.Collaboration 
{ 
    using System;
    using System.Net.Sockets; 
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices; 
    using System.Net.Mail;
    using System.Security.Cryptography.X509Certificates; 
    using System.ComponentModel; 
    using System.Threading;
    using System.Diagnostics; 

    /// 
    /// This is the event args class we give back when
    /// we have completed the createcontactasync call 
    /// 
    public class CreateContactCompletedEventArgs : AsyncCompletedEventArgs 
    { 
        private PeerContact m_peerContact;
        internal CreateContactCompletedEventArgs(   PeerContact peerContact, 
                                                    Exception error,
                                                    bool cancelled,
                                                    object userToken)
            : base(error, cancelled, userToken) 
        {
            m_peerContact = peerContact; 
        } 

        public PeerContact PeerContact 
        {
            get{
                return m_peerContact;
            } 
        }
    } 
 
    /// 
    /// This is the event args class we give back when 
    /// we have a subscription changed event from native
    /// 
    public class SubscriptionListChangedEventArgs : EventArgs
    { 
        private PeerEndPoint m_peerEndPoint;
        private PeerContact m_peerContact; 
        private PeerChangeType m_peerChangeType; 

        internal SubscriptionListChangedEventArgs(PeerEndPoint peerEndPoint, PeerContact peerContact, 
                                              PeerChangeType peerChangeType)
        {
            m_peerEndPoint = peerEndPoint;
            m_peerContact = peerContact; 
            m_peerChangeType = peerChangeType;
        } 
 
        public PeerEndPoint PeerEndPoint
        { 
            get
            {
                return m_peerEndPoint;
            } 
        }
 
        public PeerContact PeerContact 
        {
            get 
            {
                return m_peerContact;
            }
        } 

        public PeerChangeType PeerChangeType 
        { 
            get
            { 
                return m_peerChangeType;
            }
        }
 
    }
 
    ///  
    /// This class handles all the operation related to contacts and thier storage in the
    /// Windows Address Book 
    /// 
    public sealed class ContactManager : IDisposable
    {
        private ISynchronizeInvoke m_synchronizingObject; 

        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        internal ContactManager()
        {
            CollaborationHelperFunctions.Initialize();
 
            OnCreateContactCompletedDelegate = new SendOrPostCallback(CreateContactCompletedWaitCallback);
        } 
 
        //
        // Returns the peer collaboration users' contact 
        //
        public static PeerContact LocalContact
        {
            //  
            // 
            //  
            //  
            // 
            //  
            // 
            // 
            // 
            [System.Security.SecurityCritical] 
            get
            { 
                SafeCollabData contact = null; 
                MyContact myContact;
                PEER_CONTACT pc; 

                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact called.");

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
                CollaborationHelperFunctions.Initialize();
 
                try{ 
                    //
                    // Get my contact from native with null peer name 
                    //

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(null, out contact);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0,
                                    "PeerCollabGetContact returned with errorcode {0}", errorCode); 
                        return null; 
                    }
                    pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT)); 
                    myContact = (MyContact) CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc, true);
                }
                finally{
                    if (contact != null) contact.Dispose(); 
                }
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact successful."); 

                return myContact; 
            }
        }

        ///  
        /// Gets and set the object used to marshall event handlers calls for stand alone
        /// events 
        ///  
        [Browsable(false), DefaultValue(null), Description(SR.SynchronizingObject)]
        public ISynchronizeInvoke SynchronizingObject 
        {
            get
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
                return m_synchronizingObject;
            } 
            set 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
                m_synchronizingObject = value;
            }
        }
 
        private event EventHandler m_subscriptionListChanged;
        public event EventHandler SubscriptionListChanged 
        { 
            // 
            //  
            // 
            [System.Security.SecurityCritical]
            add
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddSubscriptionListChanged(value); 
            }
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            remove 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                RemoveSubscriptionListChanged(value);
            } 
        }
 
        #region Subcription list changed event variables 
        private object m_lockSubLstChangedEvent;
        private object LockSubLstChangedEvent 
        {
            get{
                if (m_lockSubLstChangedEvent == null){
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockSubLstChangedEvent, o, null);
                } 
                return m_lockSubLstChangedEvent; 
            }
        } 

        private RegisteredWaitHandle m_regSubLstChangedWaitHandle;
        private AutoResetEvent m_subLstChangedEvent;
        private SafeCollabEvent m_safeSubLstChangedEvent; 
        #endregion
 
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void AddSubscriptionListChanged(EventHandler callback) 
        { 
            //
            // Register a wait handle if one has not been registered already 
            //

            lock (LockSubLstChangedEvent){
                if (m_subscriptionListChanged == null){ 
                    m_subLstChangedEvent = new AutoResetEvent(false);
 
                    // 
                    // Register callback with a wait handle
                    // 

                    m_regSubLstChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_subLstChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(SubListChangedCallback), //callback to be called
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
 
                    pcer.eventType = PeerCollabEventType.WatchListChanged;
                    pcer.pInstance = IntPtr.Zero;

                    // 
                    // Register event with collab
                    // 
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_subLstChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer,
                                                                        out m_safeSubLstChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_SubListChangedRegFailed), errorCode); 
                    } 
                }
                m_subscriptionListChanged += callback; 
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddSubscriptionListChanged() successful.");
        } 

        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void RemoveSubscriptionListChanged(EventHandler callback)
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() called."); 

            lock (LockSubLstChangedEvent){ 
                m_subscriptionListChanged -= callback; 
                if (m_subscriptionListChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle, 
                                                                ref m_safeSubLstChangedEvent,
                                                                ref m_subLstChangedEvent);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful.");
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() successful."); 
        } 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        private void SubListChangedCallback(object state, bool timedOut)
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "SubListChangedCallback() called.");
 
            while (true){
                SubscriptionListChangedEventArgs subListChangedArgs = null;

                // 
                // Get the event data for the fired event
                // 
                try{ 
                    lock (LockSubLstChangedEvent){
                        if (m_safeSubLstChangedEvent.IsInvalid) return; 
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeSubLstChangedEvent,
                                                                                     out eventData);
                    }
 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break; 
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetSubListChangedDataFailed), errorCode); 
                    }

                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 

                    if (ped.eventType == PeerCollabEventType.WatchListChanged){ 
                        PEER_EVENT_WATCHLIST_CHANGED_DATA watchlistData = ped.watchListChangedData; 

                        PeerContact peerContact = null; 

                        if (watchlistData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(watchlistData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }
 
 
                        subListChangedArgs = new SubscriptionListChangedEventArgs(null,
                                                                                        peerContact, 
                                                                                        watchlistData.changeType);

                    }
                } 
                finally{
                    if (eventData != null) eventData.Dispose(); 
                } 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_subscriptionListChanged; 

                if ((subListChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, subListChangedArgs });
                    else 
                        handlerCopy(this, subListChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the subscription list changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving SubListChangedCallback().");
        } 
 
        private event EventHandler m_nameChanged;
        public event EventHandler NameChanged 
        {
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            add 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                AddNameChanged(value);
            } 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveNameChanged(value); 
            } 
        }
 
        #region Name changed event variables
        private object m_lockNameChangedEvent;
        private object LockNameChangedEvent
        { 
            get{
                if (m_lockNameChangedEvent == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockNameChangedEvent, o, null);
                } 
                return m_lockNameChangedEvent;
            }
        }
        private RegisteredWaitHandle m_regNameChangedWaitHandle; 
        private AutoResetEvent m_nameChangedEvent;
        private SafeCollabEvent m_safeNameChangedEvent; 
        #endregion 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private void AddNameChanged(EventHandler callback)
        { 
            //
            // Register a wait handle if one has not been registered already
            //
 
            lock (LockNameChangedEvent){
                if (m_nameChanged == null){ 
 
                    m_nameChangedEvent = new AutoResetEvent(false);
 
                    //
                    // Register callback with a wait handle
                    //
 
                    m_regNameChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_nameChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(NameChangedCallback), //callback to be called 
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();

                    pcer.eventType = PeerCollabEventType.EndPointChanged; 
                    pcer.pInstance = IntPtr.Zero;
 
                    // 
                    // Register event with collab
                    // 

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_nameChangedEvent.SafeWaitHandle,
                                                                        1, 
                                                                        ref pcer,
                                                                        out m_safeNameChangedEvent); 
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_NameChangedRegFailed), errorCode); 
                    }
                }
                m_nameChanged += callback;
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddNameChanged() successful."); 
        } 

        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        private void RemoveNameChanged(EventHandler callback)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() called."); 
            lock (LockNameChangedEvent){
                m_nameChanged -= callback; 
                if (m_nameChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle,
                                                                ref m_safeNameChangedEvent,
                                                                ref m_nameChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
                } 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() successful.");
        } 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void NameChangedCallback(object state, bool timedOut) 
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "NameChangedCallback() called.");

            while (true){ 
                NameChangedEventArgs nameChangedArgs = null;
 
                // 
                // Get the event data for the fired event
                // 
                try{
                    lock (LockNameChangedEvent){
                        if (m_safeNameChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeNameChangedEvent, 
                                                                                     out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break;
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetNameChangedDataFailed), errorCode);
                    }
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 
 
                    if (ped.eventType == PeerCollabEventType.EndPointChanged){
                        PEER_EVENT_ENDPOINT_CHANGED_DATA endpointData = ped.endpointChangedData; 

                        PeerContact peerContact = null;
                        PeerEndPoint peerEndPoint = null;
                        string newName = null; 

                        if (endpointData.pContact != IntPtr.Zero){ 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(endpointData.pContact, typeof(PEER_CONTACT)); 
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
                        } 

                        if (endpointData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(endpointData.pEndPoint, typeof(PEER_ENDPOINT));
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe); 
                            newName = peerEndPoint.Name;
                        } 
 
                        nameChangedArgs = new NameChangedEventArgs(peerEndPoint,
                                                                    peerContact, 
                                                                    newName);
                    }
                }
                finally{ 
                    if(eventData != null) eventData.Dispose();
                } 
 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_nameChanged; 

                if ((nameChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, nameChangedArgs });
                    else 
                        handlerCopy(this, nameChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the name changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving NameChangedCallback().");
        } 
 
        private event EventHandler m_presenceChanged;
        public event EventHandler PresenceChanged 
        {
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            add 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                AddPresenceChanged(value);
            } 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemovePresenceChanged(value); 
            } 
        }
 
        #region Presence changed event variables
        private object m_lockPresenceChangedEvent;
        private object LockPresenceChangedEvent
        { 
            get{
                if (m_lockPresenceChangedEvent == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockPresenceChangedEvent, o, null);
                } 
                return m_lockPresenceChangedEvent;
            }
        }
        private RegisteredWaitHandle m_regPresenceChangedWaitHandle; 
        private AutoResetEvent m_presenceChangedEvent;
        private SafeCollabEvent m_safePresenceChangedEvent; 
        #endregion 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private void AddPresenceChanged(EventHandler callback)
        { 
            //
            // Register a wait handle if one has not been registered already
            //
 
            lock (LockPresenceChangedEvent){
                if (m_presenceChanged == null){ 
 
                    m_presenceChangedEvent = new AutoResetEvent(false);
 
                    //
                    // Register callback with a wait handle
                    //
 
                    m_regPresenceChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_presenceChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(PresenceChangedCallback), //callback to be called 
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
                    pcer.eventType = PeerCollabEventType.EndPointPresenceChanged;
                    pcer.pInstance = IntPtr.Zero; 

                    // 
                    // Register event with collab 
                    //
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_presenceChangedEvent.SafeWaitHandle,
                                                                        1,
                                                                        ref pcer, 
                                                                        out m_safePresenceChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PresenceChangedRegFailed), errorCode);
                    } 
                }
                m_presenceChanged += callback;
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPresenceChanged() successful.");
        } 
 
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void RemovePresenceChanged(EventHandler callback) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() called."); 
 
            lock (LockPresenceChangedEvent){
                m_presenceChanged -= callback; 
                if (m_presenceChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
                                                                ref m_safePresenceChangedEvent,
                                                                ref m_presenceChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
                } 
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() successful."); 
        }

        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private void PresenceChangedCallback(object state, bool timedOut) 
        {
            SafeCollabData eventData = null; 
            int errorCode = 0;

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PresenceChangedCallback() called.");
 
            while (true){
                PresenceChangedEventArgs presenceChangedArgs = null; 
                // 
                // Get the event data for the fired event
                // 
                try{
                    lock (LockPresenceChangedEvent){
                        if (m_safePresenceChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safePresenceChangedEvent, 
                                                                                                                out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break;
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPresenceChangedDataFailed), errorCode);
                    }
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 
 

                    if (ped.eventType == PeerCollabEventType.EndPointPresenceChanged){ 
                        PEER_EVENT_PRESENCE_CHANGED_DATA presenceData = ped.presenceChangedData;

                        PeerPresenceInfo peerPresenceInfo = null;
                        if (presenceData.pPresenceInfo != IntPtr.Zero){ 
                            PEER_PRESENCE_INFO ppi = (PEER_PRESENCE_INFO)Marshal.PtrToStructure(presenceData.pPresenceInfo, typeof(PEER_PRESENCE_INFO));
                            peerPresenceInfo = new PeerPresenceInfo(); 
                            peerPresenceInfo.PresenceStatus = ppi.status; 
                            peerPresenceInfo.DescriptiveText = ppi.descText;
                        } 

                        PeerContact peerContact = null;
                        PeerEndPoint peerEndPoint = null;
 
                        if (presenceData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(presenceData.pContact, typeof(PEER_CONTACT)); 
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }
 
                        if (presenceData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(presenceData.pEndPoint, typeof(PEER_ENDPOINT));
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 

                        presenceChangedArgs = new PresenceChangedEventArgs(peerEndPoint, 
                                                                                        peerContact, 
                                                                                        presenceData.changeType,
                                                                                        peerPresenceInfo); 
                    }
                }
                finally{
                    if(eventData != null) eventData.Dispose(); 
                }
 
                // 
                // Fire the callback with the marshalled event args data
                // 

                EventHandler handlerCopy = m_presenceChanged;

                if ((presenceChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, presenceChangedArgs }); 
                    else 
                        handlerCopy(this, presenceChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the presence changed event callback."); 
                }
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PresenceChangedCallback().");
        } 

        private event EventHandler m_applicationChanged; 
        public event EventHandler ApplicationChanged 
        {
            //  
            // 
            // 
            [System.Security.SecurityCritical]
            add{ 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddApplicationChanged(value); 
            }
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            remove{ 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveApplicationChanged(value);
            }
        } 

        #region Application changed event variables 
        private object m_lockAppChangedEvent; 
        private object LockAppChangedEvent
        { 
            get{
                if (m_lockAppChangedEvent == null){
                    object o = new object();
                    Interlocked.CompareExchange(ref m_lockAppChangedEvent, o, null); 
                }
                return m_lockAppChangedEvent; 
            } 
        }
        private RegisteredWaitHandle m_regAppChangedWaitHandle; 
        private AutoResetEvent m_appChangedEvent;
        private SafeCollabEvent m_safeAppChangedEvent;
        #endregion
 
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void AddApplicationChanged(EventHandler callback) 
        {
            // 
            // Register a wait handle if one has not been registered already 
            //
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() called.");

            lock (LockAppChangedEvent){
                if (m_applicationChanged == null){ 

                    m_appChangedEvent = new AutoResetEvent(false); 
 
                    //
                    // Register callback with a wait handle 
                    //

                    m_regAppChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_appChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(ApplicationChangedCallback), //callback to be called 
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers 
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION(); 
                    pcer.eventType = PeerCollabEventType.EndPointApplicationChanged;
                    pcer.pInstance = IntPtr.Zero;

                    // 
                    // Register event with collab
                    // 
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_appChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer,
                                                                        out m_safeAppChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ApplicationChangedRegFailed), errorCode); 
                    } 
                }
                m_applicationChanged += callback; 
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() successful.");
        } 

        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void RemoveApplicationChanged(EventHandler callback)
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() called."); 

            lock (LockAppChangedEvent){ 
                m_applicationChanged -= callback; 
                if (m_applicationChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle, 
                                                                ref m_safeAppChangedEvent,
                                                                ref m_appChangedEvent);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful.");
                } 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() successful."); 
        }
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void ApplicationChangedCallback(object state, bool timedOut) 
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ApplicationChangedCallback() called.");

            while (true) 
            {
                ApplicationChangedEventArgs appChangedArgs = null; 
 
                //
                // Get the event data for the fired event 
                //
                try
                {
                    lock (LockAppChangedEvent){ 
                        if (m_safeAppChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeAppChangedEvent, 
                                                                                     out eventData); 
                    }
 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break;
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetApplicationChangedDataFailed), errorCode);
                    } 
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                                typeof(PEER_COLLAB_EVENT_DATA)); 
                    if (ped.eventType == PeerCollabEventType.EndPointApplicationChanged){
                        PEER_EVENT_APPLICATION_CHANGED_DATA appData = ped.applicationChangedData;
                        PEER_APPLICATION pa = (PEER_APPLICATION)Marshal.PtrToStructure(appData.pApplication, typeof(PEER_APPLICATION));
 
                        PeerApplication peerApplication = CollaborationHelperFunctions.ConvertPEER_APPLICATIONToPeerApplication(pa); ;
 
                        PeerContact peerContact = null; 
                        PeerEndPoint peerEndPoint = null;
 
                        if (appData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(appData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
                        } 

                        if (appData.pEndPoint != IntPtr.Zero){ 
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(appData.pEndPoint, typeof(PEER_ENDPOINT)); 
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 

                        appChangedArgs = new ApplicationChangedEventArgs(peerEndPoint,
                                                                peerContact,
                                                                appData.changeType, 
                                                                peerApplication);
                    } 
                } 
                finally{
                    if(eventData != null) eventData.Dispose(); 
                }

                //
                // Fire the callback with the marshalled event args data 
                //
 
                EventHandler handlerCopy = m_applicationChanged; 

                if ((appChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, appChangedArgs });
                    else
                        handlerCopy(this, appChangedArgs); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the application changed event callback.");
                } 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ApplicationChangedCallback().");
        } 

        private event EventHandler m_objectChanged;
        public event EventHandler ObjectChanged
        { 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            add 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddObjectChangedEvent(value); 
            } 
            // 
            //  
            // 
            [System.Security.SecurityCritical]
            remove
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveObjectChangedEvent(value); 
            }
        }

        #region Object changed event variables 
        private object m_lockObjChangedEvent;
        private object LockObjChangedEvent 
        { 
            get{
                if (m_lockObjChangedEvent == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref m_lockObjChangedEvent, o, null);
                }
                return m_lockObjChangedEvent; 
            }
        } 
        private RegisteredWaitHandle m_regObjChangedWaitHandle; 
        private AutoResetEvent m_objChangedEvent;
        private SafeCollabEvent m_safeObjChangedEvent; 
        #endregion

        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void AddObjectChangedEvent(EventHandler callback)
        {
            // 
            // Register a wait handle if one has not been registered already
            // 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChangedEvent() called.");
 
            lock (LockObjChangedEvent){
                if (m_objectChanged == null){

                    m_objChangedEvent = new AutoResetEvent(false); 

                    // 
                    // Register callback with a wait handle 
                    //
 
                    m_regObjChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_objChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(ObjectChangedCallback), //callback to be called
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers 
                                            false //call us everytime the event is set
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION(); 
                    pcer.eventType = PeerCollabEventType.EndPointObjectChanged;
                    pcer.pInstance = IntPtr.Zero; 

                    //
                    // Register event with collab
                    // 

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent( 
                                                                        m_objChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer, 
                                                                        out m_safeObjChangedEvent);
                    if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ObjectChangedRegFailed), errorCode); 
                    }
                } 
                m_objectChanged += callback; 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChanged() successful.");
        }

        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        private void RemoveObjectChangedEvent(EventHandler callback) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() called.");

            lock (LockObjChangedEvent){ 
                m_objectChanged -= callback;
                if (m_objectChanged == null){ 
                    CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle, 
                                                                ref m_safeObjChangedEvent,
                                                                ref m_objChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful.");
                }
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() successful.");
        } 
 
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void ObjectChangedCallback(object state, bool timedOut) 
        {
            SafeCollabData eventData = null; 
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ObjectChangedCallback() called."); 

            while (true)
            {
                ObjectChangedEventArgs objectChangedArgs = null; 

                // 
                // Get the event data for the fired event 
                //
                try{ 
                    lock (LockObjChangedEvent){
                        if (m_safeObjChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeObjChangedEvent,
                                                                                     out eventData); 
                    }
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break; 
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectChangedDataFailed), errorCode);
                    }

                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(), 
                                                                                                typeof(PEER_COLLAB_EVENT_DATA));
 
                    if (ped.eventType == PeerCollabEventType.EndPointObjectChanged){ 
                        PEER_EVENT_OBJECT_CHANGED_DATA objData = ped.objectChangedData;
                        PEER_OBJECT po = (PEER_OBJECT)Marshal.PtrToStructure(objData.pObject, typeof(PEER_OBJECT)); 

                        PeerObject peerObject = CollaborationHelperFunctions.ConvertPEER_OBJECTToPeerObject(po);

                        PeerContact peerContact = null; 
                        PeerEndPoint peerEndPoint = null;
 
                        if (objData.pContact != IntPtr.Zero){ 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(objData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }

                        if (objData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(objData.pEndPoint, typeof(PEER_ENDPOINT)); 
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 
 
                        objectChangedArgs = new ObjectChangedEventArgs(peerEndPoint,
                                                                                                peerContact, 
                                                                                                objData.changeType,
                                                                                                peerObject);
                    }
                } 
                finally{
                    if(eventData != null) eventData.Dispose(); 
                } 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_objectChanged; 

                if ((objectChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, objectChangedArgs });
                    else 
                        handlerCopy(this, objectChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the object changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ObjectChangedCallback().");
        } 
 
        //
        // Grabs all the contacts from the users windows address book 
        //
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        public PeerContactCollection GetContacts()
        { 
            PeerContactCollection peerContactColl = new PeerContactCollection();
            SafeCollabEnum handlePeerEnum = null;
            UInt32 contactCount = 0;
            int errorCode = 0; 

            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering GetContacts()");

            try{
                // 
                // Get contacts array from native
                // 
 
                errorCode = UnsafeCollabNativeMethods.PeerCollabEnumContacts(out handlePeerEnum);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabEnumContacts returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                }
 
                errorCode = UnsafeCollabNativeMethods.PeerGetItemCount(handlePeerEnum, ref contactCount);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetItemCount returned with errorcode {0}", errorCode); 
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                } 

                if (contactCount == 0){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contacts found. \nLeaving GetContacts()");
                    return peerContactColl; 
                }
                unsafe{ 
                    SafeCollabData contactArray = null; 
                    try{
                        errorCode = UnsafeCollabNativeMethods.PeerGetNextItem(handlePeerEnum, ref contactCount, out contactArray); 
                        if (errorCode != 0){
                            Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetNextItem returned with errorcode {0}", errorCode);
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                        } 

                        // 
                        // Loop through the contacts array to build PeerContact collection 
                        //
 
                        IntPtr pPEER_CONTACT = contactArray.DangerousGetHandle();
                        IntPtr* pContacts = (IntPtr*)pPEER_CONTACT;
                        for (ulong i = 0; i < contactCount; i++){
                            IntPtr pContactPtr = (IntPtr)pContacts[i]; 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(pContactPtr, typeof(PEER_CONTACT));
 
                            PeerContact peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                            peerContactColl.Add(peerContact);
                        } 
                    }
                    finally{
                        contactArray.Dispose();
                    } 
                }
            } 
            finally{ 
                handlePeerEnum.Dispose();
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                "Returning collections with {0} contacts. \nLeaving GetContacts()");
 
            return peerContactColl;
        } 
 
        //
        // Gets specific contact from the users windows address book 
        //
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public PeerContact GetContact(PeerName peerName)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerName == null)
                throw new ArgumentNullException("peerName"); 

            int errorCode = 0;
            SafeCollabData safeContact = null;
            PeerContact peerContact = null; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                "Entering GetContact() with peername {0}", peerName.ToString()); 

            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(peerName.ToString(),
                                                                        out safeContact);
                if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager"); 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_ContactNotFound));
                } 
                else if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactFailed), errorCode); 
                }

                if (!safeContact.DangerousGetHandle().Equals(IntPtr.Zero)){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found contact."); 
                    PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(safeContact.DangerousGetHandle(), typeof(PEER_CONTACT));
                    peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                } 
                else{
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contact found."); 
                }
            }
            finally{
                safeContact.Dispose(); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving GetContact()"); 
 
            return peerContact;
        } 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public PeerContact CreateContact(PeerNearMe peerNearMe) 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            if (peerNearMe == null) 
                throw new ArgumentNullException("peerNearMe");
 
            if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContact() with peernearme", peerNearMe.ToString());

            PeerEndPoint peerEndPoint = peerNearMe.PeerEndPoints[0];
 
            PEER_ENDPOINT pe = new PEER_ENDPOINT();
            pe.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint); 
 
            //
            // Pin all the data to pass to native 
            //
            GCHandle pepName = new GCHandle();

            if (peerEndPoint.Name != null){ 
                pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
                pe.pwzEndpointName = pepName.AddrOfPinnedObject(); 
            } 

            GCHandle peerEP = GCHandle.Alloc(pe, GCHandleType.Pinned); 
            IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();

            string contactData = null;
            int errorCode = 0; 

            // 
            // Refresh end point data if it not subscribed 
            //
            peerNearMe.RefreshData(); 

            errorCode = UnsafeCollabNativeMethods.PeerCollabQueryContactData(ptrPeerEP, ref contactData);
            if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode); 
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode);
            } 
 
            SafeCollabData contact = null;
            PeerContact peerContact = null; 

            try{
                errorCode = UnsafeCollabNativeMethods.PeerCollabParseContact(contactData, out contact);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode); 
                } 

                PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT)); 
                peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);

                //
                // Mark it as just created and add the xml. This is used when adding the contact or getting 
                // contact xml when contact is not added
                // 
                peerContact.JustCreated = true; 
                peerContact.ContactXml = contactData;
            } 
            finally{
                if (contact != null) contact.Dispose();
                pepName.Free();
                peerEP.Free(); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContact()."); 
 
            return peerContact;
        } 

        SendOrPostCallback OnCreateContactCompletedDelegate;
        object m_createContactAsyncListLock;
        object CreateContactAsyncListLock 
        {
            get{ 
                if (m_createContactAsyncListLock == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref m_createContactAsyncListLock, o, null); 
                }
                return m_createContactAsyncListLock;
            }
        } 
        Dictionary m_createContactAsyncList = new Dictionary();
 
        private event EventHandler m_createContactCompleted; 
        public event EventHandler CreateContactCompleted
        { 
            add
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
                m_createContactCompleted += value; 
            }
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                m_createContactCompleted -= value; 
            } 
        }
 

        //
        // Stores state to pass to the create contact async helper
        // 
        private class CreateContactAsyncState
        { 
            PeerNearMe m_peerNearMe; 
            Object m_userToken;
            internal CreateContactAsyncState(PeerNearMe peerNearMe, Object userToken){ 
                m_peerNearMe = peerNearMe;
                m_userToken = userToken;
            }
            internal PeerNearMe PeerNearMe 
            {
                get { return m_peerNearMe; } 
            } 
            internal Object UserToken
            { 
                get { return m_userToken; }
            }
        }
 
        public void CreateContactAsync(PeerNearMe peerNearMe, Object userToken)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (peerNearMe == null)
                throw new ArgumentNullException("PeerNearMe");
 
            if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContactAsync() with token {0} and following peernearme" , userToken); 
                peerNearMe.TracePeerNearMe();
            }

            // 
            // Add to list of usertokens
            // 
            lock (CreateContactAsyncListLock){ 
                if (m_createContactAsyncList.ContainsKey(userToken)){
                    throw new ArgumentException(SR.GetString(SR.DuplicateUserToken)); 
                }
                AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userToken);
                m_createContactAsyncList[userToken] = asyncOp;
            } 

            ThreadPool.QueueUserWorkItem(new WaitCallback(CreateContactAsyncHelper), new CreateContactAsyncState(peerNearMe, userToken)); 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContactAsync().");
 
        }

        //
        // Used to create a contact async'ally 
        //
        private void CreateContactAsyncHelper(object state) 
        { 
            Exception ex = null;
            PeerContact peerContact = null; 
            CreateContactAsyncState createAsyncState = state as CreateContactAsyncState;
            PeerNearMe peerNearMe = createAsyncState.PeerNearMe;
            object userToken = createAsyncState.UserToken;
 
            //
            // Call the [....] version of createcontact 
            // 
            try{
                peerContact = CreateContact(peerNearMe); 
            }
            catch (ObjectDisposedException e){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message);
                ex = e; 
            }
            catch (PeerToPeerException e){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message); 
                ex = e;
            } 

            CreateContactCompletedEventArgs createContactCompletedArgs;
            if (ex == null){
                createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, null, false, userToken); 
            }
            else{ 
                createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, ex, false, userToken); 
            }
 
            PrepareToRaiseCreateContactCompletedEvent(m_createContactAsyncList[userToken], createContactCompletedArgs);
        }

        void OnCreateContactCompleted(CreateContactCompletedEventArgs e) 
        {
            EventHandler handlerCopy = m_createContactCompleted; 
            if (handlerCopy != null){ 
                handlerCopy(this, e);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the create contact completed event callback."); 
            }
        }

        void CreateContactCompletedWaitCallback(object operationState) 
        {
            CreateContactCompletedEventArgs args = (CreateContactCompletedEventArgs) operationState; 
            // 
            // Remove from usertoken list
            // 
            m_createContactAsyncList.Remove(args.UserState);

            OnCreateContactCompleted(args);
        } 

        internal void PrepareToRaiseCreateContactCompletedEvent(AsyncOperation asyncOP, CreateContactCompletedEventArgs args) 
        { 
            asyncOP.PostOperationCompleted(OnCreateContactCompletedDelegate, args);
        } 

        //
        // Adds a contacts to the users windows address book
        // 
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public void AddContact(PeerContact peerContact)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (peerContact == null) 
                throw new ArgumentNullException("peerContact");

            string contactXml = null;
 
            if (peerContact.ContactXml == null){
                try{ 
                    contactXml = peerContact.ToXml(); 
                }
                catch (PeerToPeerException e){ 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_AddContactFailedNoXml), e.InnerException);
                }
            }
            else{ 
                contactXml = peerContact.ContactXml;
            } 
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddContact() with following peercontact"); 
                peerContact.TracePeerContact();
            }

            SafeCollabData contact = null; 
            int errorCode = 0;
 
            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabAddContact(contactXml, out contact);
            } 
            finally{
                if(contact != null) contact.Dispose();
            }
 
            if (errorCode == UnsafeCollabReturnCodes.PEER_E_ALREADY_EXISTS){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}. Contact already exists.", errorCode); 
                throw new ArgumentException(SR.GetString(SR.Collab_AddContactFailed) + " " + SR.GetString(SR.Collab_ContactExists)); 
            }
            else if (errorCode != 0){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}", errorCode);
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_AddContactFailed), errorCode);
            }
 
            peerContact.JustCreated = false;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                                    "Leaving AddContact() successfully."); 

        } 

        //
        // Deletes a contact from the users windows address book
        // 
        public void DeleteContact(PeerContact peerContact)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                            "Entering DeleteContact().");
 
            if (peerContact == null)
                throw new ArgumentNullException("peerContact");

            DeleteContact(peerContact.PeerName); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                            "Leaving DeleteContact() successfully."); 
 
        }
 
        //
        // Deletes a contact from the users windows address book
        //
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public void DeleteContact(PeerName peerName) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                        "Entering DeleteContact().");
 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerName == null)
                throw new ArgumentNullException("peerName"); 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                        "Peername is {0}", peerName.ToString());
 
            int errorCode = UnsafeCollabNativeMethods.PeerCollabDeleteContact(peerName.ToString());
 
            if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
                throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerName"); 
            }
            else if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabDeleteContact returned with errorcode {0}", errorCode);
                throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_DeleteContactFailed), errorCode)); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                        "Leaving DeleteContact() successfully."); 
        }
 
        //
        // Updates a contact from the users windows address book
        //
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public void UpdateContact(PeerContact peerContact)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerContact == null)
                throw new ArgumentNullException("peerContact"); 

            if (peerContact.PeerName == null)
                throw new ArgumentException(SR.GetString(SR.Collab_NoPeerNameInContact));
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering UpdateContact() with following peercontact"); 
                peerContact.TracePeerContact(); 
            }
 
            SafeCollabMemory safeCredentials = null;
            int errorCode = 0;

            try{ 
                PEER_CONTACT pc = CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(peerContact, ref safeCredentials);
 
                errorCode = UnsafeCollabNativeMethods.PeerCollabUpdateContact(ref pc); 
            }
            finally{ 
                if (safeCredentials != null) safeCredentials.Dispose();
            }

            if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
                throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerContact"); 
            } 
            else if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabUpdateContact returned with errorcode {0}", errorCode); 
                throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_UpdateContactFailed), errorCode));
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                                        "Leaving UpdateContact() successfully."); 
        }
 
        private bool m_Disposed; 

        //  
        // 
        // 
        [System.Security.SecurityCritical]
        public void Dispose() 
        {
            Dispose(true); 
            GC.SuppressFinalize(this); 
        }
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        void Dispose(bool disposing)
        {
            if (!m_Disposed){
                CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle, 
                                                            ref m_safeSubLstChangedEvent,
                                                            ref m_subLstChangedEvent); 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful."); 

                CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle, 
                                                            ref m_safeNameChangedEvent,
                                                            ref m_nameChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
 
                CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
                                                            ref m_safePresenceChangedEvent, 
                                                            ref m_presenceChangedEvent); 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
 
                CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle,
                                                            ref m_safeAppChangedEvent,
                                                            ref m_appChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful."); 

                CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle, 
                                                            ref m_safeObjChangedEvent, 
                                                            ref m_objChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful."); 

                m_Disposed = true;
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net.PeerToPeer.Collaboration 
{ 
    using System;
    using System.Net.Sockets; 
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices; 
    using System.Net.Mail;
    using System.Security.Cryptography.X509Certificates; 
    using System.ComponentModel; 
    using System.Threading;
    using System.Diagnostics; 

    /// 
    /// This is the event args class we give back when
    /// we have completed the createcontactasync call 
    /// 
    public class CreateContactCompletedEventArgs : AsyncCompletedEventArgs 
    { 
        private PeerContact m_peerContact;
        internal CreateContactCompletedEventArgs(   PeerContact peerContact, 
                                                    Exception error,
                                                    bool cancelled,
                                                    object userToken)
            : base(error, cancelled, userToken) 
        {
            m_peerContact = peerContact; 
        } 

        public PeerContact PeerContact 
        {
            get{
                return m_peerContact;
            } 
        }
    } 
 
    /// 
    /// This is the event args class we give back when 
    /// we have a subscription changed event from native
    /// 
    public class SubscriptionListChangedEventArgs : EventArgs
    { 
        private PeerEndPoint m_peerEndPoint;
        private PeerContact m_peerContact; 
        private PeerChangeType m_peerChangeType; 

        internal SubscriptionListChangedEventArgs(PeerEndPoint peerEndPoint, PeerContact peerContact, 
                                              PeerChangeType peerChangeType)
        {
            m_peerEndPoint = peerEndPoint;
            m_peerContact = peerContact; 
            m_peerChangeType = peerChangeType;
        } 
 
        public PeerEndPoint PeerEndPoint
        { 
            get
            {
                return m_peerEndPoint;
            } 
        }
 
        public PeerContact PeerContact 
        {
            get 
            {
                return m_peerContact;
            }
        } 

        public PeerChangeType PeerChangeType 
        { 
            get
            { 
                return m_peerChangeType;
            }
        }
 
    }
 
    ///  
    /// This class handles all the operation related to contacts and thier storage in the
    /// Windows Address Book 
    /// 
    public sealed class ContactManager : IDisposable
    {
        private ISynchronizeInvoke m_synchronizingObject; 

        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        internal ContactManager()
        {
            CollaborationHelperFunctions.Initialize();
 
            OnCreateContactCompletedDelegate = new SendOrPostCallback(CreateContactCompletedWaitCallback);
        } 
 
        //
        // Returns the peer collaboration users' contact 
        //
        public static PeerContact LocalContact
        {
            //  
            // 
            //  
            //  
            // 
            //  
            // 
            // 
            // 
            [System.Security.SecurityCritical] 
            get
            { 
                SafeCollabData contact = null; 
                MyContact myContact;
                PEER_CONTACT pc; 

                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact called.");

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
                CollaborationHelperFunctions.Initialize();
 
                try{ 
                    //
                    // Get my contact from native with null peer name 
                    //

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(null, out contact);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0,
                                    "PeerCollabGetContact returned with errorcode {0}", errorCode); 
                        return null; 
                    }
                    pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT)); 
                    myContact = (MyContact) CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc, true);
                }
                finally{
                    if (contact != null) contact.Dispose(); 
                }
 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact successful."); 

                return myContact; 
            }
        }

        ///  
        /// Gets and set the object used to marshall event handlers calls for stand alone
        /// events 
        ///  
        [Browsable(false), DefaultValue(null), Description(SR.SynchronizingObject)]
        public ISynchronizeInvoke SynchronizingObject 
        {
            get
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
                return m_synchronizingObject;
            } 
            set 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
                m_synchronizingObject = value;
            }
        }
 
        private event EventHandler m_subscriptionListChanged;
        public event EventHandler SubscriptionListChanged 
        { 
            // 
            //  
            // 
            [System.Security.SecurityCritical]
            add
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddSubscriptionListChanged(value); 
            }
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            remove 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                RemoveSubscriptionListChanged(value);
            } 
        }
 
        #region Subcription list changed event variables 
        private object m_lockSubLstChangedEvent;
        private object LockSubLstChangedEvent 
        {
            get{
                if (m_lockSubLstChangedEvent == null){
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockSubLstChangedEvent, o, null);
                } 
                return m_lockSubLstChangedEvent; 
            }
        } 

        private RegisteredWaitHandle m_regSubLstChangedWaitHandle;
        private AutoResetEvent m_subLstChangedEvent;
        private SafeCollabEvent m_safeSubLstChangedEvent; 
        #endregion
 
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void AddSubscriptionListChanged(EventHandler callback) 
        { 
            //
            // Register a wait handle if one has not been registered already 
            //

            lock (LockSubLstChangedEvent){
                if (m_subscriptionListChanged == null){ 
                    m_subLstChangedEvent = new AutoResetEvent(false);
 
                    // 
                    // Register callback with a wait handle
                    // 

                    m_regSubLstChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_subLstChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(SubListChangedCallback), //callback to be called
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
 
                    pcer.eventType = PeerCollabEventType.WatchListChanged;
                    pcer.pInstance = IntPtr.Zero;

                    // 
                    // Register event with collab
                    // 
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_subLstChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer,
                                                                        out m_safeSubLstChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_SubListChangedRegFailed), errorCode); 
                    } 
                }
                m_subscriptionListChanged += callback; 
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddSubscriptionListChanged() successful.");
        } 

        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void RemoveSubscriptionListChanged(EventHandler callback)
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() called."); 

            lock (LockSubLstChangedEvent){ 
                m_subscriptionListChanged -= callback; 
                if (m_subscriptionListChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle, 
                                                                ref m_safeSubLstChangedEvent,
                                                                ref m_subLstChangedEvent);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful.");
                } 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() successful."); 
        } 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        private void SubListChangedCallback(object state, bool timedOut)
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "SubListChangedCallback() called.");
 
            while (true){
                SubscriptionListChangedEventArgs subListChangedArgs = null;

                // 
                // Get the event data for the fired event
                // 
                try{ 
                    lock (LockSubLstChangedEvent){
                        if (m_safeSubLstChangedEvent.IsInvalid) return; 
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeSubLstChangedEvent,
                                                                                     out eventData);
                    }
 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break; 
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetSubListChangedDataFailed), errorCode); 
                    }

                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 

                    if (ped.eventType == PeerCollabEventType.WatchListChanged){ 
                        PEER_EVENT_WATCHLIST_CHANGED_DATA watchlistData = ped.watchListChangedData; 

                        PeerContact peerContact = null; 

                        if (watchlistData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(watchlistData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }
 
 
                        subListChangedArgs = new SubscriptionListChangedEventArgs(null,
                                                                                        peerContact, 
                                                                                        watchlistData.changeType);

                    }
                } 
                finally{
                    if (eventData != null) eventData.Dispose(); 
                } 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_subscriptionListChanged; 

                if ((subListChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, subListChangedArgs });
                    else 
                        handlerCopy(this, subListChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the subscription list changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving SubListChangedCallback().");
        } 
 
        private event EventHandler m_nameChanged;
        public event EventHandler NameChanged 
        {
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            add 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                AddNameChanged(value);
            } 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveNameChanged(value); 
            } 
        }
 
        #region Name changed event variables
        private object m_lockNameChangedEvent;
        private object LockNameChangedEvent
        { 
            get{
                if (m_lockNameChangedEvent == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockNameChangedEvent, o, null);
                } 
                return m_lockNameChangedEvent;
            }
        }
        private RegisteredWaitHandle m_regNameChangedWaitHandle; 
        private AutoResetEvent m_nameChangedEvent;
        private SafeCollabEvent m_safeNameChangedEvent; 
        #endregion 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private void AddNameChanged(EventHandler callback)
        { 
            //
            // Register a wait handle if one has not been registered already
            //
 
            lock (LockNameChangedEvent){
                if (m_nameChanged == null){ 
 
                    m_nameChangedEvent = new AutoResetEvent(false);
 
                    //
                    // Register callback with a wait handle
                    //
 
                    m_regNameChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_nameChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(NameChangedCallback), //callback to be called 
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();

                    pcer.eventType = PeerCollabEventType.EndPointChanged; 
                    pcer.pInstance = IntPtr.Zero;
 
                    // 
                    // Register event with collab
                    // 

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_nameChangedEvent.SafeWaitHandle,
                                                                        1, 
                                                                        ref pcer,
                                                                        out m_safeNameChangedEvent); 
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_NameChangedRegFailed), errorCode); 
                    }
                }
                m_nameChanged += callback;
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddNameChanged() successful."); 
        } 

        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        private void RemoveNameChanged(EventHandler callback)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() called."); 
            lock (LockNameChangedEvent){
                m_nameChanged -= callback; 
                if (m_nameChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle,
                                                                ref m_safeNameChangedEvent,
                                                                ref m_nameChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
                } 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() successful.");
        } 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void NameChangedCallback(object state, bool timedOut) 
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "NameChangedCallback() called.");

            while (true){ 
                NameChangedEventArgs nameChangedArgs = null;
 
                // 
                // Get the event data for the fired event
                // 
                try{
                    lock (LockNameChangedEvent){
                        if (m_safeNameChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeNameChangedEvent, 
                                                                                     out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break;
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetNameChangedDataFailed), errorCode);
                    }
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 
 
                    if (ped.eventType == PeerCollabEventType.EndPointChanged){
                        PEER_EVENT_ENDPOINT_CHANGED_DATA endpointData = ped.endpointChangedData; 

                        PeerContact peerContact = null;
                        PeerEndPoint peerEndPoint = null;
                        string newName = null; 

                        if (endpointData.pContact != IntPtr.Zero){ 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(endpointData.pContact, typeof(PEER_CONTACT)); 
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
                        } 

                        if (endpointData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(endpointData.pEndPoint, typeof(PEER_ENDPOINT));
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe); 
                            newName = peerEndPoint.Name;
                        } 
 
                        nameChangedArgs = new NameChangedEventArgs(peerEndPoint,
                                                                    peerContact, 
                                                                    newName);
                    }
                }
                finally{ 
                    if(eventData != null) eventData.Dispose();
                } 
 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_nameChanged; 

                if ((nameChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, nameChangedArgs });
                    else 
                        handlerCopy(this, nameChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the name changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving NameChangedCallback().");
        } 
 
        private event EventHandler m_presenceChanged;
        public event EventHandler PresenceChanged 
        {
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            add 
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

                AddPresenceChanged(value);
            } 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemovePresenceChanged(value); 
            } 
        }
 
        #region Presence changed event variables
        private object m_lockPresenceChangedEvent;
        private object LockPresenceChangedEvent
        { 
            get{
                if (m_lockPresenceChangedEvent == null){ 
                    object o = new object(); 
                    Interlocked.CompareExchange(ref m_lockPresenceChangedEvent, o, null);
                } 
                return m_lockPresenceChangedEvent;
            }
        }
        private RegisteredWaitHandle m_regPresenceChangedWaitHandle; 
        private AutoResetEvent m_presenceChangedEvent;
        private SafeCollabEvent m_safePresenceChangedEvent; 
        #endregion 

        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private void AddPresenceChanged(EventHandler callback)
        { 
            //
            // Register a wait handle if one has not been registered already
            //
 
            lock (LockPresenceChangedEvent){
                if (m_presenceChanged == null){ 
 
                    m_presenceChangedEvent = new AutoResetEvent(false);
 
                    //
                    // Register callback with a wait handle
                    //
 
                    m_regPresenceChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_presenceChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(PresenceChangedCallback), //callback to be called 
                                            null, //state to be passed 
                                            -1,   //Timeout - aplicable only for timers
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
                    pcer.eventType = PeerCollabEventType.EndPointPresenceChanged;
                    pcer.pInstance = IntPtr.Zero; 

                    // 
                    // Register event with collab 
                    //
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_presenceChangedEvent.SafeWaitHandle,
                                                                        1,
                                                                        ref pcer, 
                                                                        out m_safePresenceChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PresenceChangedRegFailed), errorCode);
                    } 
                }
                m_presenceChanged += callback;
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPresenceChanged() successful.");
        } 
 
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void RemovePresenceChanged(EventHandler callback) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() called."); 
 
            lock (LockPresenceChangedEvent){
                m_presenceChanged -= callback; 
                if (m_presenceChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
                                                                ref m_safePresenceChangedEvent,
                                                                ref m_presenceChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
                } 
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() successful."); 
        }

        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private void PresenceChangedCallback(object state, bool timedOut) 
        {
            SafeCollabData eventData = null; 
            int errorCode = 0;

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PresenceChangedCallback() called.");
 
            while (true){
                PresenceChangedEventArgs presenceChangedArgs = null; 
                // 
                // Get the event data for the fired event
                // 
                try{
                    lock (LockPresenceChangedEvent){
                        if (m_safePresenceChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safePresenceChangedEvent, 
                                                                                                                out eventData);
                    } 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break;
                    else if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPresenceChangedDataFailed), errorCode);
                    }
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                            typeof(PEER_COLLAB_EVENT_DATA)); 
 

                    if (ped.eventType == PeerCollabEventType.EndPointPresenceChanged){ 
                        PEER_EVENT_PRESENCE_CHANGED_DATA presenceData = ped.presenceChangedData;

                        PeerPresenceInfo peerPresenceInfo = null;
                        if (presenceData.pPresenceInfo != IntPtr.Zero){ 
                            PEER_PRESENCE_INFO ppi = (PEER_PRESENCE_INFO)Marshal.PtrToStructure(presenceData.pPresenceInfo, typeof(PEER_PRESENCE_INFO));
                            peerPresenceInfo = new PeerPresenceInfo(); 
                            peerPresenceInfo.PresenceStatus = ppi.status; 
                            peerPresenceInfo.DescriptiveText = ppi.descText;
                        } 

                        PeerContact peerContact = null;
                        PeerEndPoint peerEndPoint = null;
 
                        if (presenceData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(presenceData.pContact, typeof(PEER_CONTACT)); 
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }
 
                        if (presenceData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(presenceData.pEndPoint, typeof(PEER_ENDPOINT));
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 

                        presenceChangedArgs = new PresenceChangedEventArgs(peerEndPoint, 
                                                                                        peerContact, 
                                                                                        presenceData.changeType,
                                                                                        peerPresenceInfo); 
                    }
                }
                finally{
                    if(eventData != null) eventData.Dispose(); 
                }
 
                // 
                // Fire the callback with the marshalled event args data
                // 

                EventHandler handlerCopy = m_presenceChanged;

                if ((presenceChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, presenceChangedArgs }); 
                    else 
                        handlerCopy(this, presenceChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the presence changed event callback."); 
                }
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PresenceChangedCallback().");
        } 

        private event EventHandler m_applicationChanged; 
        public event EventHandler ApplicationChanged 
        {
            //  
            // 
            // 
            [System.Security.SecurityCritical]
            add{ 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddApplicationChanged(value); 
            }
            // 
            // 
            //  
            [System.Security.SecurityCritical]
            remove{ 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveApplicationChanged(value);
            }
        } 

        #region Application changed event variables 
        private object m_lockAppChangedEvent; 
        private object LockAppChangedEvent
        { 
            get{
                if (m_lockAppChangedEvent == null){
                    object o = new object();
                    Interlocked.CompareExchange(ref m_lockAppChangedEvent, o, null); 
                }
                return m_lockAppChangedEvent; 
            } 
        }
        private RegisteredWaitHandle m_regAppChangedWaitHandle; 
        private AutoResetEvent m_appChangedEvent;
        private SafeCollabEvent m_safeAppChangedEvent;
        #endregion
 
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void AddApplicationChanged(EventHandler callback) 
        {
            // 
            // Register a wait handle if one has not been registered already 
            //
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() called.");

            lock (LockAppChangedEvent){
                if (m_applicationChanged == null){ 

                    m_appChangedEvent = new AutoResetEvent(false); 
 
                    //
                    // Register callback with a wait handle 
                    //

                    m_regAppChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_appChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(ApplicationChangedCallback), //callback to be called 
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers 
                                            false //call us everytime the event is set 
                                            );
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION(); 
                    pcer.eventType = PeerCollabEventType.EndPointApplicationChanged;
                    pcer.pInstance = IntPtr.Zero;

                    // 
                    // Register event with collab
                    // 
 
                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
                                                                        m_appChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer,
                                                                        out m_safeAppChangedEvent);
                    if (errorCode != 0){ 
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ApplicationChangedRegFailed), errorCode); 
                    } 
                }
                m_applicationChanged += callback; 
            }

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() successful.");
        } 

        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void RemoveApplicationChanged(EventHandler callback)
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() called."); 

            lock (LockAppChangedEvent){ 
                m_applicationChanged -= callback; 
                if (m_applicationChanged == null){
                    CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle, 
                                                                ref m_safeAppChangedEvent,
                                                                ref m_appChangedEvent);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful.");
                } 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() successful."); 
        }
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        private void ApplicationChangedCallback(object state, bool timedOut) 
        { 
            SafeCollabData eventData = null;
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ApplicationChangedCallback() called.");

            while (true) 
            {
                ApplicationChangedEventArgs appChangedArgs = null; 
 
                //
                // Get the event data for the fired event 
                //
                try
                {
                    lock (LockAppChangedEvent){ 
                        if (m_safeAppChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeAppChangedEvent, 
                                                                                     out eventData); 
                    }
 
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
                        break;
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetApplicationChangedDataFailed), errorCode);
                    } 
 
                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
                                                                                                typeof(PEER_COLLAB_EVENT_DATA)); 
                    if (ped.eventType == PeerCollabEventType.EndPointApplicationChanged){
                        PEER_EVENT_APPLICATION_CHANGED_DATA appData = ped.applicationChangedData;
                        PEER_APPLICATION pa = (PEER_APPLICATION)Marshal.PtrToStructure(appData.pApplication, typeof(PEER_APPLICATION));
 
                        PeerApplication peerApplication = CollaborationHelperFunctions.ConvertPEER_APPLICATIONToPeerApplication(pa); ;
 
                        PeerContact peerContact = null; 
                        PeerEndPoint peerEndPoint = null;
 
                        if (appData.pContact != IntPtr.Zero){
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(appData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
                        } 

                        if (appData.pEndPoint != IntPtr.Zero){ 
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(appData.pEndPoint, typeof(PEER_ENDPOINT)); 
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 

                        appChangedArgs = new ApplicationChangedEventArgs(peerEndPoint,
                                                                peerContact,
                                                                appData.changeType, 
                                                                peerApplication);
                    } 
                } 
                finally{
                    if(eventData != null) eventData.Dispose(); 
                }

                //
                // Fire the callback with the marshalled event args data 
                //
 
                EventHandler handlerCopy = m_applicationChanged; 

                if ((appChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, appChangedArgs });
                    else
                        handlerCopy(this, appChangedArgs); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the application changed event callback.");
                } 
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ApplicationChangedCallback().");
        } 

        private event EventHandler m_objectChanged;
        public event EventHandler ObjectChanged
        { 
            // 
            //  
            //  
            [System.Security.SecurityCritical]
            add 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                AddObjectChangedEvent(value); 
            } 
            // 
            //  
            // 
            [System.Security.SecurityCritical]
            remove
            { 
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                RemoveObjectChangedEvent(value); 
            }
        }

        #region Object changed event variables 
        private object m_lockObjChangedEvent;
        private object LockObjChangedEvent 
        { 
            get{
                if (m_lockObjChangedEvent == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref m_lockObjChangedEvent, o, null);
                }
                return m_lockObjChangedEvent; 
            }
        } 
        private RegisteredWaitHandle m_regObjChangedWaitHandle; 
        private AutoResetEvent m_objChangedEvent;
        private SafeCollabEvent m_safeObjChangedEvent; 
        #endregion

        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        private void AddObjectChangedEvent(EventHandler callback)
        {
            // 
            // Register a wait handle if one has not been registered already
            // 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChangedEvent() called.");
 
            lock (LockObjChangedEvent){
                if (m_objectChanged == null){

                    m_objChangedEvent = new AutoResetEvent(false); 

                    // 
                    // Register callback with a wait handle 
                    //
 
                    m_regObjChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_objChangedEvent, //Event that triggers the callback
                                            new WaitOrTimerCallback(ObjectChangedCallback), //callback to be called
                                            null, //state to be passed
                                            -1,   //Timeout - aplicable only for timers 
                                            false //call us everytime the event is set
                                            ); 
                    PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION(); 
                    pcer.eventType = PeerCollabEventType.EndPointObjectChanged;
                    pcer.pInstance = IntPtr.Zero; 

                    //
                    // Register event with collab
                    // 

                    int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent( 
                                                                        m_objChangedEvent.SafeWaitHandle, 
                                                                        1,
                                                                        ref pcer, 
                                                                        out m_safeObjChangedEvent);
                    if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ObjectChangedRegFailed), errorCode); 
                    }
                } 
                m_objectChanged += callback; 
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChanged() successful.");
        }

        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        private void RemoveObjectChangedEvent(EventHandler callback) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() called.");

            lock (LockObjChangedEvent){ 
                m_objectChanged -= callback;
                if (m_objectChanged == null){ 
                    CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle, 
                                                                ref m_safeObjChangedEvent,
                                                                ref m_objChangedEvent); 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful.");
                }
            }
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() successful.");
        } 
 
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        private void ObjectChangedCallback(object state, bool timedOut) 
        {
            SafeCollabData eventData = null; 
            int errorCode = 0; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ObjectChangedCallback() called."); 

            while (true)
            {
                ObjectChangedEventArgs objectChangedArgs = null; 

                // 
                // Get the event data for the fired event 
                //
                try{ 
                    lock (LockObjChangedEvent){
                        if (m_safeObjChangedEvent.IsInvalid) return;
                        errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeObjChangedEvent,
                                                                                     out eventData); 
                    }
                    if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA) 
                        break; 
                    else if (errorCode != 0){
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode); 
                        throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectChangedDataFailed), errorCode);
                    }

                    PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(), 
                                                                                                typeof(PEER_COLLAB_EVENT_DATA));
 
                    if (ped.eventType == PeerCollabEventType.EndPointObjectChanged){ 
                        PEER_EVENT_OBJECT_CHANGED_DATA objData = ped.objectChangedData;
                        PEER_OBJECT po = (PEER_OBJECT)Marshal.PtrToStructure(objData.pObject, typeof(PEER_OBJECT)); 

                        PeerObject peerObject = CollaborationHelperFunctions.ConvertPEER_OBJECTToPeerObject(po);

                        PeerContact peerContact = null; 
                        PeerEndPoint peerEndPoint = null;
 
                        if (objData.pContact != IntPtr.Zero){ 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(objData.pContact, typeof(PEER_CONTACT));
                            peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                        }

                        if (objData.pEndPoint != IntPtr.Zero){
                            PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(objData.pEndPoint, typeof(PEER_ENDPOINT)); 
                            peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
                        } 
 
                        objectChangedArgs = new ObjectChangedEventArgs(peerEndPoint,
                                                                                                peerContact, 
                                                                                                objData.changeType,
                                                                                                peerObject);
                    }
                } 
                finally{
                    if(eventData != null) eventData.Dispose(); 
                } 

                // 
                // Fire the callback with the marshalled event args data
                //

                EventHandler handlerCopy = m_objectChanged; 

                if ((objectChangedArgs != null) && (handlerCopy != null)){ 
                    if (SynchronizingObject != null && SynchronizingObject.InvokeRequired) 
                        SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, objectChangedArgs });
                    else 
                        handlerCopy(this, objectChangedArgs);
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the object changed event callback.");
                }
            } 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ObjectChangedCallback().");
        } 
 
        //
        // Grabs all the contacts from the users windows address book 
        //
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        public PeerContactCollection GetContacts()
        { 
            PeerContactCollection peerContactColl = new PeerContactCollection();
            SafeCollabEnum handlePeerEnum = null;
            UInt32 contactCount = 0;
            int errorCode = 0; 

            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering GetContacts()");

            try{
                // 
                // Get contacts array from native
                // 
 
                errorCode = UnsafeCollabNativeMethods.PeerCollabEnumContacts(out handlePeerEnum);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabEnumContacts returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                }
 
                errorCode = UnsafeCollabNativeMethods.PeerGetItemCount(handlePeerEnum, ref contactCount);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetItemCount returned with errorcode {0}", errorCode); 
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                } 

                if (contactCount == 0){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contacts found. \nLeaving GetContacts()");
                    return peerContactColl; 
                }
                unsafe{ 
                    SafeCollabData contactArray = null; 
                    try{
                        errorCode = UnsafeCollabNativeMethods.PeerGetNextItem(handlePeerEnum, ref contactCount, out contactArray); 
                        if (errorCode != 0){
                            Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetNextItem returned with errorcode {0}", errorCode);
                            throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
                        } 

                        // 
                        // Loop through the contacts array to build PeerContact collection 
                        //
 
                        IntPtr pPEER_CONTACT = contactArray.DangerousGetHandle();
                        IntPtr* pContacts = (IntPtr*)pPEER_CONTACT;
                        for (ulong i = 0; i < contactCount; i++){
                            IntPtr pContactPtr = (IntPtr)pContacts[i]; 
                            PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(pContactPtr, typeof(PEER_CONTACT));
 
                            PeerContact peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                            peerContactColl.Add(peerContact);
                        } 
                    }
                    finally{
                        contactArray.Dispose();
                    } 
                }
            } 
            finally{ 
                handlePeerEnum.Dispose();
            } 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                "Returning collections with {0} contacts. \nLeaving GetContacts()");
 
            return peerContactColl;
        } 
 
        //
        // Gets specific contact from the users windows address book 
        //
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public PeerContact GetContact(PeerName peerName)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerName == null)
                throw new ArgumentNullException("peerName"); 

            int errorCode = 0;
            SafeCollabData safeContact = null;
            PeerContact peerContact = null; 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                "Entering GetContact() with peername {0}", peerName.ToString()); 

            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(peerName.ToString(),
                                                                        out safeContact);
                if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager"); 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_ContactNotFound));
                } 
                else if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactFailed), errorCode); 
                }

                if (!safeContact.DangerousGetHandle().Equals(IntPtr.Zero)){
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found contact."); 
                    PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(safeContact.DangerousGetHandle(), typeof(PEER_CONTACT));
                    peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc); 
                } 
                else{
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contact found."); 
                }
            }
            finally{
                safeContact.Dispose(); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving GetContact()"); 
 
            return peerContact;
        } 

        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public PeerContact CreateContact(PeerNearMe peerNearMe) 
        {
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();

            if (peerNearMe == null) 
                throw new ArgumentNullException("peerNearMe");
 
            if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null)) 
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContact() with peernearme", peerNearMe.ToString());

            PeerEndPoint peerEndPoint = peerNearMe.PeerEndPoints[0];
 
            PEER_ENDPOINT pe = new PEER_ENDPOINT();
            pe.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint); 
 
            //
            // Pin all the data to pass to native 
            //
            GCHandle pepName = new GCHandle();

            if (peerEndPoint.Name != null){ 
                pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
                pe.pwzEndpointName = pepName.AddrOfPinnedObject(); 
            } 

            GCHandle peerEP = GCHandle.Alloc(pe, GCHandleType.Pinned); 
            IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();

            string contactData = null;
            int errorCode = 0; 

            // 
            // Refresh end point data if it not subscribed 
            //
            peerNearMe.RefreshData(); 

            errorCode = UnsafeCollabNativeMethods.PeerCollabQueryContactData(ptrPeerEP, ref contactData);
            if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode); 
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode);
            } 
 
            SafeCollabData contact = null;
            PeerContact peerContact = null; 

            try{
                errorCode = UnsafeCollabNativeMethods.PeerCollabParseContact(contactData, out contact);
                if (errorCode != 0){ 
                    Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
                    throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode); 
                } 

                PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT)); 
                peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);

                //
                // Mark it as just created and add the xml. This is used when adding the contact or getting 
                // contact xml when contact is not added
                // 
                peerContact.JustCreated = true; 
                peerContact.ContactXml = contactData;
            } 
            finally{
                if (contact != null) contact.Dispose();
                pepName.Free();
                peerEP.Free(); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContact()."); 
 
            return peerContact;
        } 

        SendOrPostCallback OnCreateContactCompletedDelegate;
        object m_createContactAsyncListLock;
        object CreateContactAsyncListLock 
        {
            get{ 
                if (m_createContactAsyncListLock == null){ 
                    object o = new object();
                    Interlocked.CompareExchange(ref m_createContactAsyncListLock, o, null); 
                }
                return m_createContactAsyncListLock;
            }
        } 
        Dictionary m_createContactAsyncList = new Dictionary();
 
        private event EventHandler m_createContactCompleted; 
        public event EventHandler CreateContactCompleted
        { 
            add
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
 
                m_createContactCompleted += value; 
            }
            remove 
            {
                if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);

                PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

                m_createContactCompleted -= value; 
            } 
        }
 

        //
        // Stores state to pass to the create contact async helper
        // 
        private class CreateContactAsyncState
        { 
            PeerNearMe m_peerNearMe; 
            Object m_userToken;
            internal CreateContactAsyncState(PeerNearMe peerNearMe, Object userToken){ 
                m_peerNearMe = peerNearMe;
                m_userToken = userToken;
            }
            internal PeerNearMe PeerNearMe 
            {
                get { return m_peerNearMe; } 
            } 
            internal Object UserToken
            { 
                get { return m_userToken; }
            }
        }
 
        public void CreateContactAsync(PeerNearMe peerNearMe, Object userToken)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); 

            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (peerNearMe == null)
                throw new ArgumentNullException("PeerNearMe");
 
            if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null))
                throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound)); 
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContactAsync() with token {0} and following peernearme" , userToken); 
                peerNearMe.TracePeerNearMe();
            }

            // 
            // Add to list of usertokens
            // 
            lock (CreateContactAsyncListLock){ 
                if (m_createContactAsyncList.ContainsKey(userToken)){
                    throw new ArgumentException(SR.GetString(SR.DuplicateUserToken)); 
                }
                AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userToken);
                m_createContactAsyncList[userToken] = asyncOp;
            } 

            ThreadPool.QueueUserWorkItem(new WaitCallback(CreateContactAsyncHelper), new CreateContactAsyncState(peerNearMe, userToken)); 
 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContactAsync().");
 
        }

        //
        // Used to create a contact async'ally 
        //
        private void CreateContactAsyncHelper(object state) 
        { 
            Exception ex = null;
            PeerContact peerContact = null; 
            CreateContactAsyncState createAsyncState = state as CreateContactAsyncState;
            PeerNearMe peerNearMe = createAsyncState.PeerNearMe;
            object userToken = createAsyncState.UserToken;
 
            //
            // Call the [....] version of createcontact 
            // 
            try{
                peerContact = CreateContact(peerNearMe); 
            }
            catch (ObjectDisposedException e){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message);
                ex = e; 
            }
            catch (PeerToPeerException e){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message); 
                ex = e;
            } 

            CreateContactCompletedEventArgs createContactCompletedArgs;
            if (ex == null){
                createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, null, false, userToken); 
            }
            else{ 
                createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, ex, false, userToken); 
            }
 
            PrepareToRaiseCreateContactCompletedEvent(m_createContactAsyncList[userToken], createContactCompletedArgs);
        }

        void OnCreateContactCompleted(CreateContactCompletedEventArgs e) 
        {
            EventHandler handlerCopy = m_createContactCompleted; 
            if (handlerCopy != null){ 
                handlerCopy(this, e);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the create contact completed event callback."); 
            }
        }

        void CreateContactCompletedWaitCallback(object operationState) 
        {
            CreateContactCompletedEventArgs args = (CreateContactCompletedEventArgs) operationState; 
            // 
            // Remove from usertoken list
            // 
            m_createContactAsyncList.Remove(args.UserState);

            OnCreateContactCompleted(args);
        } 

        internal void PrepareToRaiseCreateContactCompletedEvent(AsyncOperation asyncOP, CreateContactCompletedEventArgs args) 
        { 
            asyncOP.PostOperationCompleted(OnCreateContactCompletedDelegate, args);
        } 

        //
        // Adds a contacts to the users windows address book
        // 
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public void AddContact(PeerContact peerContact)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 

            if (peerContact == null) 
                throw new ArgumentNullException("peerContact");

            string contactXml = null;
 
            if (peerContact.ContactXml == null){
                try{ 
                    contactXml = peerContact.ToXml(); 
                }
                catch (PeerToPeerException e){ 
                    throw new PeerToPeerException(SR.GetString(SR.Collab_AddContactFailedNoXml), e.InnerException);
                }
            }
            else{ 
                contactXml = peerContact.ContactXml;
            } 
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddContact() with following peercontact"); 
                peerContact.TracePeerContact();
            }

            SafeCollabData contact = null; 
            int errorCode = 0;
 
            try{ 
                errorCode = UnsafeCollabNativeMethods.PeerCollabAddContact(contactXml, out contact);
            } 
            finally{
                if(contact != null) contact.Dispose();
            }
 
            if (errorCode == UnsafeCollabReturnCodes.PEER_E_ALREADY_EXISTS){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}. Contact already exists.", errorCode); 
                throw new ArgumentException(SR.GetString(SR.Collab_AddContactFailed) + " " + SR.GetString(SR.Collab_ContactExists)); 
            }
            else if (errorCode != 0){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}", errorCode);
                throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_AddContactFailed), errorCode);
            }
 
            peerContact.JustCreated = false;
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                                    "Leaving AddContact() successfully."); 

        } 

        //
        // Deletes a contact from the users windows address book
        // 
        public void DeleteContact(PeerContact peerContact)
        { 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                            "Entering DeleteContact().");
 
            if (peerContact == null)
                throw new ArgumentNullException("peerContact");

            DeleteContact(peerContact.PeerName); 
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                            "Leaving DeleteContact() successfully."); 
 
        }
 
        //
        // Deletes a contact from the users windows address book
        //
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public void DeleteContact(PeerName peerName) 
        {
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                        "Entering DeleteContact().");
 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerName == null)
                throw new ArgumentNullException("peerName"); 

            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                        "Peername is {0}", peerName.ToString());
 
            int errorCode = UnsafeCollabNativeMethods.PeerCollabDeleteContact(peerName.ToString());
 
            if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
                throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerName"); 
            }
            else if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabDeleteContact returned with errorcode {0}", errorCode);
                throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_DeleteContactFailed), errorCode)); 
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
                        "Leaving DeleteContact() successfully."); 
        }
 
        //
        // Updates a contact from the users windows address book
        //
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        [System.Security.SecurityCritical]
        public void UpdateContact(PeerContact peerContact)
        { 
            if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
 
            PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand(); 
            if (peerContact == null)
                throw new ArgumentNullException("peerContact"); 

            if (peerContact.PeerName == null)
                throw new ArgumentException(SR.GetString(SR.Collab_NoPeerNameInContact));
 
            if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering UpdateContact() with following peercontact"); 
                peerContact.TracePeerContact(); 
            }
 
            SafeCollabMemory safeCredentials = null;
            int errorCode = 0;

            try{ 
                PEER_CONTACT pc = CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(peerContact, ref safeCredentials);
 
                errorCode = UnsafeCollabNativeMethods.PeerCollabUpdateContact(ref pc); 
            }
            finally{ 
                if (safeCredentials != null) safeCredentials.Dispose();
            }

            if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){ 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
                throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerContact"); 
            } 
            else if (errorCode != 0){
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabUpdateContact returned with errorcode {0}", errorCode); 
                throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_UpdateContactFailed), errorCode));
            }
            Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
                                        "Leaving UpdateContact() successfully."); 
        }
 
        private bool m_Disposed; 

        //  
        // 
        // 
        [System.Security.SecurityCritical]
        public void Dispose() 
        {
            Dispose(true); 
            GC.SuppressFinalize(this); 
        }
 
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        void Dispose(bool disposing)
        {
            if (!m_Disposed){
                CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle, 
                                                            ref m_safeSubLstChangedEvent,
                                                            ref m_subLstChangedEvent); 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful."); 

                CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle, 
                                                            ref m_safeNameChangedEvent,
                                                            ref m_nameChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
 
                CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
                                                            ref m_safePresenceChangedEvent, 
                                                            ref m_presenceChangedEvent); 
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
 
                CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle,
                                                            ref m_safeAppChangedEvent,
                                                            ref m_appChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful."); 

                CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle, 
                                                            ref m_safeObjChangedEvent, 
                                                            ref m_objChangedEvent);
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful."); 

                m_Disposed = true;
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK