Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Net / net / PeerToPeer / Collaboration / ContactManager.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ContactManager.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Net.PeerToPeer.Collaboration
8 {
9     using System;
10     using System.Net.Sockets;
11     using System.Collections.Specialized;
12     using System.Collections.Generic;
13     using System.Text;
14     using System.Runtime.InteropServices;
15     using System.Net.Mail;
16     using System.Security.Cryptography.X509Certificates;
17     using System.ComponentModel;
18     using System.Threading;
19     using System.Diagnostics;
20
21     /// <summary>
22     /// This is the event args class we give back when 
23     /// we have completed the createcontactasync call
24     /// </summary>
25     public class CreateContactCompletedEventArgs : AsyncCompletedEventArgs
26     {
27         private PeerContact m_peerContact;
28         internal CreateContactCompletedEventArgs(   PeerContact peerContact,
29                                                     Exception error,
30                                                     bool cancelled,
31                                                     object userToken)
32             : base(error, cancelled, userToken)
33         {
34             m_peerContact = peerContact;
35         }
36
37         public PeerContact PeerContact
38         {
39             get{
40                 return m_peerContact;
41             }
42         }
43     }
44
45     /// <summary>
46     /// This is the event args class we give back when 
47     /// we have a subscription changed event from native 
48     /// </summary>
49     public class SubscriptionListChangedEventArgs : EventArgs
50     {
51         private PeerEndPoint m_peerEndPoint;
52         private PeerContact m_peerContact;
53         private PeerChangeType m_peerChangeType;
54
55         internal SubscriptionListChangedEventArgs(PeerEndPoint peerEndPoint, PeerContact peerContact,
56                                               PeerChangeType peerChangeType)
57         {
58             m_peerEndPoint = peerEndPoint;
59             m_peerContact = peerContact;
60             m_peerChangeType = peerChangeType;
61         }
62
63         public PeerEndPoint PeerEndPoint
64         {
65             get
66             {
67                 return m_peerEndPoint;
68             }
69         }
70
71         public PeerContact PeerContact
72         {
73             get
74             {
75                 return m_peerContact;
76             }
77         }
78
79         public PeerChangeType PeerChangeType
80         {
81             get
82             {
83                 return m_peerChangeType;
84             }
85         }
86
87     }
88
89     /// <summary>
90     /// This class handles all the operation related to contacts and thier storage in the 
91     /// Windows Address Book
92     /// </summary>
93     public sealed class ContactManager : IDisposable
94     {
95         private ISynchronizeInvoke m_synchronizingObject;
96
97         // <SecurityKernel Critical="True" Ring="1">
98         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
99         // </SecurityKernel>
100         [System.Security.SecurityCritical]
101         internal ContactManager() 
102         {
103             CollaborationHelperFunctions.Initialize();
104
105             OnCreateContactCompletedDelegate = new SendOrPostCallback(CreateContactCompletedWaitCallback);
106         }
107
108         //
109         // Returns the peer collaboration users' contact
110         //
111         public static PeerContact LocalContact
112         {
113             // <SecurityKernel Critical="True" Ring="0">
114             // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetContact(System.String,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
115             // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
116             // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
117             // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
118             // <ReferencesCritical Name="Local contact of type: SafeCollabData" Ring="1" />
119             // <ReferencesCritical Name="Method: CollaborationHelperFunctions.Initialize():System.Void" Ring="1" />
120             // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT,System.Boolean):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="1" />
121             // </SecurityKernel>
122             [System.Security.SecurityCritical]
123             get
124             {
125                 SafeCollabData contact = null;
126                 MyContact myContact; 
127                 PEER_CONTACT pc;
128
129                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact called.");
130                 
131                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
132                 CollaborationHelperFunctions.Initialize();
133
134                 try{
135                     //
136                     // Get my contact from native with null peer name
137                     //
138
139                     int errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(null, out contact);
140                     if (errorCode != 0){
141                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0,
142                                     "PeerCollabGetContact returned with errorcode {0}", errorCode);
143                         return null;
144                     }
145                     pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT));
146                     myContact = (MyContact) CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc, true);
147                 }
148                 finally{
149                     if (contact != null) contact.Dispose();
150                 }
151
152                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Get MyContact successful.");
153
154                 return myContact;
155             }
156         }
157
158         /// <summary>
159         /// Gets and set the object used to marshall event handlers calls for stand alone 
160         /// events
161         /// </summary>
162         [Browsable(false), DefaultValue(null), Description(SR.SynchronizingObject)]
163         public ISynchronizeInvoke SynchronizingObject
164         {
165             get
166             {
167                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
168                 return m_synchronizingObject;
169             }
170             set
171             {
172                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
173                 m_synchronizingObject = value;
174             }
175         }
176
177         private event EventHandler<SubscriptionListChangedEventArgs> m_subscriptionListChanged;
178         public event EventHandler<SubscriptionListChangedEventArgs> SubscriptionListChanged
179         {
180             // <SecurityKernel Critical="True" Ring="1">
181             // <ReferencesCritical Name="Method: AddSubscriptionListChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.SubscriptionListChangedEventArgs>):Void" Ring="1" />
182             // </SecurityKernel>
183             [System.Security.SecurityCritical]
184             add
185             {
186                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
187                 
188                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
189
190                 AddSubscriptionListChanged(value);
191             }
192             // <SecurityKernel Critical="True" Ring="2">
193             // <ReferencesCritical Name="Method: RemoveSubscriptionListChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.SubscriptionListChangedEventArgs>):Void" Ring="2" />
194             // </SecurityKernel>
195             [System.Security.SecurityCritical]
196             remove
197             {
198                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
199                 
200                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
201
202                 RemoveSubscriptionListChanged(value);
203             }
204         }
205
206         #region Subcription list changed event variables
207         private object m_lockSubLstChangedEvent;
208         private object LockSubLstChangedEvent
209         {
210             get{
211                 if (m_lockSubLstChangedEvent == null){
212                     object o = new object();
213                     Interlocked.CompareExchange(ref m_lockSubLstChangedEvent, o, null);
214                 }
215                 return m_lockSubLstChangedEvent;
216             }
217         }
218
219         private RegisteredWaitHandle m_regSubLstChangedWaitHandle;
220         private AutoResetEvent m_subLstChangedEvent;
221         private SafeCollabEvent m_safeSubLstChangedEvent;
222         #endregion
223
224         // <SecurityKernel Critical="True" Ring="0">
225         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
226         // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
227         // <ReferencesCritical Name="Method: SubListChangedCallback(Object, Boolean):Void" Ring="1" />
228         // <ReferencesCritical Name="Field: m_safeSubLstChangedEvent" Ring="1" />
229         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
230         // </SecurityKernel>
231         [System.Security.SecurityCritical]
232         private void AddSubscriptionListChanged(EventHandler<SubscriptionListChangedEventArgs> callback)
233         {
234             //
235             // Register a wait handle if one has not been registered already
236             //
237
238             lock (LockSubLstChangedEvent){
239                 if (m_subscriptionListChanged == null){
240                     m_subLstChangedEvent = new AutoResetEvent(false);
241
242                     //
243                     // Register callback with a wait handle
244                     //
245                     
246                     m_regSubLstChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_subLstChangedEvent, //Event that triggers the callback
247                                             new WaitOrTimerCallback(SubListChangedCallback), //callback to be called 
248                                             null, //state to be passed
249                                             -1,   //Timeout - aplicable only for timers
250                                             false //call us everytime the event is set
251                                             );
252                     PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
253
254                     pcer.eventType = PeerCollabEventType.WatchListChanged;
255                     pcer.pInstance = IntPtr.Zero;
256
257                     //
258                     // Register event with collab
259                     //
260
261                     int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
262                                                                         m_subLstChangedEvent.SafeWaitHandle,
263                                                                         1,
264                                                                         ref pcer,
265                                                                         out m_safeSubLstChangedEvent);
266                     if (errorCode != 0){
267                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
268                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_SubListChangedRegFailed), errorCode);
269                     }
270                 }
271                 m_subscriptionListChanged += callback;
272             }
273
274             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddSubscriptionListChanged() successful.");
275         }
276
277         // <SecurityKernel Critical="True" Ring="1">
278         // <ReferencesCritical Name="Field: m_safeSubLstChangedEvent" Ring="1" />
279         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
280         // </SecurityKernel>
281         [System.Security.SecurityCritical]
282         private void RemoveSubscriptionListChanged(EventHandler<SubscriptionListChangedEventArgs> callback)
283         {
284             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() called.");
285
286             lock (LockSubLstChangedEvent){
287                 m_subscriptionListChanged -= callback;
288                 if (m_subscriptionListChanged == null){
289                     CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle,
290                                                                 ref m_safeSubLstChangedEvent,
291                                                                 ref m_subLstChangedEvent);
292                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful.");
293                 }
294             }
295             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveSubscriptionListChanged() successful.");
296         }
297
298         // <SecurityKernel Critical="True" Ring="0">
299         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
300         // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
301         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
302         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
303         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
304         // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
305         // <ReferencesCritical Name="Field: m_safeSubLstChangedEvent" Ring="1" />
306         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
307         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
308         // </SecurityKernel>
309         [System.Security.SecurityCritical]
310         private void SubListChangedCallback(object state, bool timedOut)
311         {
312             SafeCollabData eventData = null;
313             int errorCode = 0;
314
315             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "SubListChangedCallback() called.");
316             
317             while (true){
318                 SubscriptionListChangedEventArgs subListChangedArgs = null;
319
320                 //
321                 // Get the event data for the fired event
322                 //
323                 try{
324                     lock (LockSubLstChangedEvent){
325                         if (m_safeSubLstChangedEvent.IsInvalid) return;
326                         errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeSubLstChangedEvent,
327                                                                                      out eventData);
328                     }
329                     
330                     if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
331                         break;
332                     else if (errorCode != 0){
333                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
334                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetSubListChangedDataFailed), errorCode);
335                     }
336
337                     PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
338                                                                             typeof(PEER_COLLAB_EVENT_DATA));
339
340                     if (ped.eventType == PeerCollabEventType.WatchListChanged){
341                         PEER_EVENT_WATCHLIST_CHANGED_DATA watchlistData = ped.watchListChangedData;
342
343                         PeerContact peerContact = null;
344
345                         if (watchlistData.pContact != IntPtr.Zero){
346                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(watchlistData.pContact, typeof(PEER_CONTACT));
347                             peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
348                         }
349
350
351                         subListChangedArgs = new SubscriptionListChangedEventArgs(null,
352                                                                                         peerContact,
353                                                                                         watchlistData.changeType);
354
355                     }
356                 }
357                 finally{
358                     if (eventData != null) eventData.Dispose();
359                 }
360
361                 //
362                 // Fire the callback with the marshalled event args data
363                 //
364
365                 EventHandler<SubscriptionListChangedEventArgs> handlerCopy = m_subscriptionListChanged;
366
367                 if ((subListChangedArgs != null) && (handlerCopy != null)){
368                     if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
369                         SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, subListChangedArgs });
370                     else
371                         handlerCopy(this, subListChangedArgs);
372                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the subscription list changed event callback.");
373                 }
374             }
375             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving SubListChangedCallback().");
376         }
377
378         private event EventHandler<NameChangedEventArgs> m_nameChanged;
379         public event EventHandler<NameChangedEventArgs> NameChanged
380         {
381             // <SecurityKernel Critical="True" Ring="1">
382             // <ReferencesCritical Name="Method: AddNameChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.NameChangedEventArgs>):Void" Ring="1" />
383             // </SecurityKernel>
384             [System.Security.SecurityCritical]
385             add
386             {
387                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
388                 
389                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
390
391                 AddNameChanged(value);
392             }
393             // <SecurityKernel Critical="True" Ring="2">
394             // <ReferencesCritical Name="Method: RemoveNameChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.NameChangedEventArgs>):Void" Ring="2" />
395             // </SecurityKernel>
396             [System.Security.SecurityCritical]
397             remove
398             {
399                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
400                 
401                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
402
403                 RemoveNameChanged(value);
404             }
405         }
406
407         #region Name changed event variables
408         private object m_lockNameChangedEvent;
409         private object LockNameChangedEvent
410         {
411             get{
412                 if (m_lockNameChangedEvent == null){
413                     object o = new object();
414                     Interlocked.CompareExchange(ref m_lockNameChangedEvent, o, null);
415                 }
416                 return m_lockNameChangedEvent;
417             }
418         }
419         private RegisteredWaitHandle m_regNameChangedWaitHandle;
420         private AutoResetEvent m_nameChangedEvent;
421         private SafeCollabEvent m_safeNameChangedEvent;
422         #endregion
423
424         // <SecurityKernel Critical="True" Ring="0">
425         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
426         // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
427         // <ReferencesCritical Name="Method: NameChangedCallback(Object, Boolean):Void" Ring="1" />
428         // <ReferencesCritical Name="Field: m_safeNameChangedEvent" Ring="1" />
429         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
430         // </SecurityKernel>
431         [System.Security.SecurityCritical]
432         private void AddNameChanged(EventHandler<NameChangedEventArgs> callback)
433         {
434             //
435             // Register a wait handle if one has not been registered already
436             //
437
438             lock (LockNameChangedEvent){
439                 if (m_nameChanged == null){
440
441                     m_nameChangedEvent = new AutoResetEvent(false);
442
443                     //
444                     // Register callback with a wait handle
445                     //
446                     
447                     m_regNameChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_nameChangedEvent, //Event that triggers the callback
448                                             new WaitOrTimerCallback(NameChangedCallback), //callback to be called 
449                                             null, //state to be passed
450                                             -1,   //Timeout - aplicable only for timers
451                                             false //call us everytime the event is set
452                                             );
453                     PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
454                     
455                     pcer.eventType = PeerCollabEventType.EndPointChanged;
456                     pcer.pInstance = IntPtr.Zero;
457
458                     //
459                     // Register event with collab
460                     //
461
462                     int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
463                                                                         m_nameChangedEvent.SafeWaitHandle,
464                                                                         1,
465                                                                         ref pcer,
466                                                                         out m_safeNameChangedEvent);
467                     if (errorCode != 0){
468                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
469                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_NameChangedRegFailed), errorCode);
470                     }
471                 }
472                 m_nameChanged += callback;
473             }
474
475             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddNameChanged() successful.");
476         }
477
478         // <SecurityKernel Critical="True" Ring="1">
479         // <ReferencesCritical Name="Field: m_safeNameChangedEvent" Ring="1" />
480         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
481         // </SecurityKernel>
482         [System.Security.SecurityCritical]
483         private void RemoveNameChanged(EventHandler<NameChangedEventArgs> callback)
484         {
485             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() called.");
486             lock (LockNameChangedEvent){
487                 m_nameChanged -= callback;
488                 if (m_nameChanged == null){
489                     CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle,
490                                                                 ref m_safeNameChangedEvent,
491                                                                 ref m_nameChangedEvent);
492                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
493                 }
494             }
495             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveNameChanged() successful.");
496         }
497
498         // <SecurityKernel Critical="True" Ring="0">
499         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
500         // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
501         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
502         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
503         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
504         // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
505         // <ReferencesCritical Name="Field: m_safeNameChangedEvent" Ring="1" />
506         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
507         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
508         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
509         // </SecurityKernel>
510         [System.Security.SecurityCritical]
511         private void NameChangedCallback(object state, bool timedOut)
512         {
513             SafeCollabData eventData = null;
514             int errorCode = 0;
515
516             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "NameChangedCallback() called.");
517             
518             while (true){
519                 NameChangedEventArgs nameChangedArgs = null;
520
521                 //
522                 // Get the event data for the fired event
523                 //
524                 try{
525                     lock (LockNameChangedEvent){
526                         if (m_safeNameChangedEvent.IsInvalid) return;
527                         errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeNameChangedEvent,
528                                                                                      out eventData);
529                     }
530                     if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
531                         break;
532                     else if (errorCode != 0){
533                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
534                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetNameChangedDataFailed), errorCode);
535                     }
536
537                     PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
538                                                                             typeof(PEER_COLLAB_EVENT_DATA));
539                     
540                     if (ped.eventType == PeerCollabEventType.EndPointChanged){
541                         PEER_EVENT_ENDPOINT_CHANGED_DATA endpointData = ped.endpointChangedData;
542
543                         PeerContact peerContact = null;
544                         PeerEndPoint peerEndPoint = null;
545                         string newName = null;
546
547                         if (endpointData.pContact != IntPtr.Zero){
548                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(endpointData.pContact, typeof(PEER_CONTACT));
549                             peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
550                         }
551
552                         if (endpointData.pEndPoint != IntPtr.Zero){
553                             PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(endpointData.pEndPoint, typeof(PEER_ENDPOINT));
554                             peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
555                             newName = peerEndPoint.Name;
556                         }
557
558                         nameChangedArgs = new NameChangedEventArgs(peerEndPoint,
559                                                                     peerContact,
560                                                                     newName);
561                     }
562                 }
563                 finally{
564                     if(eventData != null) eventData.Dispose();
565                 }
566
567
568                 //
569                 // Fire the callback with the marshalled event args data
570                 //
571
572                 EventHandler<NameChangedEventArgs> handlerCopy = m_nameChanged;
573
574                 if ((nameChangedArgs != null) && (handlerCopy != null)){
575                     if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
576                         SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, nameChangedArgs });
577                     else
578                         handlerCopy(this, nameChangedArgs);
579                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the name changed event callback.");
580                 }
581             }
582             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving NameChangedCallback().");
583         }
584
585         private event EventHandler<PresenceChangedEventArgs> m_presenceChanged;
586         public event EventHandler<PresenceChangedEventArgs> PresenceChanged
587         {
588             // <SecurityKernel Critical="True" Ring="1">
589             // <ReferencesCritical Name="Method: AddPresenceChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PresenceChangedEventArgs>):Void" Ring="1" />
590             // </SecurityKernel>
591             [System.Security.SecurityCritical]
592             add
593             {
594                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
595                 
596                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
597
598                 AddPresenceChanged(value);
599             }
600             // <SecurityKernel Critical="True" Ring="2">
601             // <ReferencesCritical Name="Method: RemovePresenceChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.PresenceChangedEventArgs>):Void" Ring="2" />
602             // </SecurityKernel>
603             [System.Security.SecurityCritical]
604             remove
605             {
606                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
607                 
608                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
609
610                 RemovePresenceChanged(value);
611             }
612         }
613
614         #region Presence changed event variables
615         private object m_lockPresenceChangedEvent;
616         private object LockPresenceChangedEvent
617         {
618             get{
619                 if (m_lockPresenceChangedEvent == null){
620                     object o = new object();
621                     Interlocked.CompareExchange(ref m_lockPresenceChangedEvent, o, null);
622                 }
623                 return m_lockPresenceChangedEvent;
624             }
625         }
626         private RegisteredWaitHandle m_regPresenceChangedWaitHandle;
627         private AutoResetEvent m_presenceChangedEvent;
628         private SafeCollabEvent m_safePresenceChangedEvent;
629         #endregion
630
631         // <SecurityKernel Critical="True" Ring="0">
632         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
633         // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
634         // <ReferencesCritical Name="Method: PresenceChangedCallback(Object, Boolean):Void" Ring="1" />
635         // <ReferencesCritical Name="Field: m_safePresenceChangedEvent" Ring="1" />
636         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
637         // </SecurityKernel>
638         [System.Security.SecurityCritical]
639         private void AddPresenceChanged(EventHandler<PresenceChangedEventArgs> callback)
640         {
641             //
642             // Register a wait handle if one has not been registered already
643             //
644
645             lock (LockPresenceChangedEvent){
646                 if (m_presenceChanged == null){
647
648                     m_presenceChangedEvent = new AutoResetEvent(false);
649
650                     //
651                     // Register callback with a wait handle
652                     //
653                     
654                     m_regPresenceChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_presenceChangedEvent, //Event that triggers the callback
655                                             new WaitOrTimerCallback(PresenceChangedCallback), //callback to be called 
656                                             null, //state to be passed
657                                             -1,   //Timeout - aplicable only for timers
658                                             false //call us everytime the event is set
659                                             );
660                     PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
661                     pcer.eventType = PeerCollabEventType.EndPointPresenceChanged;
662                     pcer.pInstance = IntPtr.Zero;
663
664                     //
665                     // Register event with collab
666                     //
667
668                     int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
669                                                                         m_presenceChangedEvent.SafeWaitHandle,
670                                                                         1,
671                                                                         ref pcer,
672                                                                         out m_safePresenceChangedEvent);
673                     if (errorCode != 0){
674                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
675                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PresenceChangedRegFailed), errorCode);
676                     }
677                 }
678                 m_presenceChanged += callback;
679             }
680
681             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddPresenceChanged() successful.");
682         }
683
684         // <SecurityKernel Critical="True" Ring="1">
685         // <ReferencesCritical Name="Field: m_safePresenceChangedEvent" Ring="1" />
686         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
687         // </SecurityKernel>
688         [System.Security.SecurityCritical]
689         private void RemovePresenceChanged(EventHandler<PresenceChangedEventArgs> callback)
690         {
691             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() called.");
692             
693             lock (LockPresenceChangedEvent){
694                 m_presenceChanged -= callback;
695                 if (m_presenceChanged == null){
696                     CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
697                                                                 ref m_safePresenceChangedEvent,
698                                                                 ref m_presenceChangedEvent);
699                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
700                 }
701             }
702
703             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemovePresenceChanged() successful.");
704         }
705
706         // <SecurityKernel Critical="True" Ring="0">
707         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
708         // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
709         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
710         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
711         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
712         // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
713         // <ReferencesCritical Name="Field: m_safePresenceChangedEvent" Ring="1" />
714         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
715         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
716         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
717         // </SecurityKernel>
718         [System.Security.SecurityCritical]
719         private void PresenceChangedCallback(object state, bool timedOut)
720         {
721             SafeCollabData eventData = null;
722             int errorCode = 0;
723
724             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "PresenceChangedCallback() called.");
725
726             while (true){
727                 PresenceChangedEventArgs presenceChangedArgs = null;
728                 //
729                 // Get the event data for the fired event
730                 //
731                 try{
732                     lock (LockPresenceChangedEvent){
733                         if (m_safePresenceChangedEvent.IsInvalid) return;
734                         errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safePresenceChangedEvent,
735                                                                                                                 out eventData);
736                     }
737                     if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
738                         break;
739                     else if (errorCode != 0){
740                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
741                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetPresenceChangedDataFailed), errorCode);
742                     }
743
744                     PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
745                                                                             typeof(PEER_COLLAB_EVENT_DATA));
746                     
747                     
748                     if (ped.eventType == PeerCollabEventType.EndPointPresenceChanged){
749                         PEER_EVENT_PRESENCE_CHANGED_DATA presenceData = ped.presenceChangedData;
750
751                         PeerPresenceInfo peerPresenceInfo = null;
752                         if (presenceData.pPresenceInfo != IntPtr.Zero){
753                             PEER_PRESENCE_INFO ppi = (PEER_PRESENCE_INFO)Marshal.PtrToStructure(presenceData.pPresenceInfo, typeof(PEER_PRESENCE_INFO));
754                             peerPresenceInfo = new PeerPresenceInfo();
755                             peerPresenceInfo.PresenceStatus = ppi.status;
756                             peerPresenceInfo.DescriptiveText = ppi.descText;
757                         }
758
759                         PeerContact peerContact = null;
760                         PeerEndPoint peerEndPoint = null;
761
762                         if (presenceData.pContact != IntPtr.Zero){
763                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(presenceData.pContact, typeof(PEER_CONTACT));
764                             peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
765                         }
766
767                         if (presenceData.pEndPoint != IntPtr.Zero){
768                             PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(presenceData.pEndPoint, typeof(PEER_ENDPOINT));
769                             peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
770                         }
771
772                         presenceChangedArgs = new PresenceChangedEventArgs(peerEndPoint,
773                                                                                         peerContact,
774                                                                                         presenceData.changeType,
775                                                                                         peerPresenceInfo);
776                     }
777                 }
778                 finally{
779                     if(eventData != null) eventData.Dispose();
780                 }
781                 
782                 //
783                 // Fire the callback with the marshalled event args data
784                 //
785
786                 EventHandler<PresenceChangedEventArgs> handlerCopy = m_presenceChanged;
787
788                 if ((presenceChangedArgs != null) && (handlerCopy != null)){
789                     if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
790                         SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, presenceChangedArgs });
791                     else
792                         handlerCopy(this, presenceChangedArgs);
793                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the presence changed event callback.");
794                 }
795             }
796             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving PresenceChangedCallback().");
797         }
798
799         private event EventHandler<ApplicationChangedEventArgs> m_applicationChanged;
800         public event EventHandler<ApplicationChangedEventArgs> ApplicationChanged
801         {
802             // <SecurityKernel Critical="True" Ring="1">
803             // <ReferencesCritical Name="Method: AddApplicationChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.ApplicationChangedEventArgs>):Void" Ring="1" />
804             // </SecurityKernel>
805             [System.Security.SecurityCritical]
806             add{
807                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
808                 
809                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
810
811                 AddApplicationChanged(value);
812             }
813             // <SecurityKernel Critical="True" Ring="2">
814             // <ReferencesCritical Name="Method: RemoveApplicationChanged(EventHandler`1<System.Net.PeerToPeer.Collaboration.ApplicationChangedEventArgs>):Void" Ring="2" />
815             // </SecurityKernel>
816             [System.Security.SecurityCritical]
817             remove{
818                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
819                 
820                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
821
822                 RemoveApplicationChanged(value);
823             }
824         }
825
826         #region Application changed event variables
827         private object m_lockAppChangedEvent;
828         private object LockAppChangedEvent
829         {
830             get{
831                 if (m_lockAppChangedEvent == null){
832                     object o = new object();
833                     Interlocked.CompareExchange(ref m_lockAppChangedEvent, o, null);
834                 }
835                 return m_lockAppChangedEvent;
836             }
837         }
838         private RegisteredWaitHandle m_regAppChangedWaitHandle;
839         private AutoResetEvent m_appChangedEvent;
840         private SafeCollabEvent m_safeAppChangedEvent;
841         #endregion
842
843         // <SecurityKernel Critical="True" Ring="0">
844         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
845         // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
846         // <ReferencesCritical Name="Method: ApplicationChangedCallback(Object, Boolean):Void" Ring="1" />
847         // <ReferencesCritical Name="Field: m_safeAppChangedEvent" Ring="1" />
848         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
849         // </SecurityKernel>
850         [System.Security.SecurityCritical]
851         private void AddApplicationChanged(EventHandler<ApplicationChangedEventArgs> callback)
852         {
853             //
854             // Register a wait handle if one has not been registered already
855             //
856
857             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() called.");
858
859             lock (LockAppChangedEvent){
860                 if (m_applicationChanged == null){
861
862                     m_appChangedEvent = new AutoResetEvent(false);
863
864                     //
865                     // Register callback with a wait handle
866                     //
867
868                     m_regAppChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_appChangedEvent, //Event that triggers the callback
869                                             new WaitOrTimerCallback(ApplicationChangedCallback), //callback to be called 
870                                             null, //state to be passed
871                                             -1,   //Timeout - aplicable only for timers
872                                             false //call us everytime the event is set
873                                             );
874                     PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
875                     pcer.eventType = PeerCollabEventType.EndPointApplicationChanged;
876                     pcer.pInstance = IntPtr.Zero;
877
878                     //
879                     // Register event with collab
880                     //
881
882                     int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
883                                                                         m_appChangedEvent.SafeWaitHandle,
884                                                                         1,
885                                                                         ref pcer,
886                                                                         out m_safeAppChangedEvent);
887                     if (errorCode != 0){
888                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
889                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ApplicationChangedRegFailed), errorCode);
890                     }
891                 }
892                 m_applicationChanged += callback;
893             }
894
895             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() successful.");
896         }
897
898         // <SecurityKernel Critical="True" Ring="1">
899         // <ReferencesCritical Name="Field: m_safeAppChangedEvent" Ring="1" />
900         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
901         // </SecurityKernel>
902         [System.Security.SecurityCritical]
903         private void RemoveApplicationChanged(EventHandler<ApplicationChangedEventArgs> callback)
904         {
905             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() called.");
906
907             lock (LockAppChangedEvent){
908                 m_applicationChanged -= callback;
909                 if (m_applicationChanged == null){
910                     CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle,
911                                                                 ref m_safeAppChangedEvent,
912                                                                 ref m_appChangedEvent);
913                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful.");
914                 }
915             }
916
917             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveApplicationChanged() successful.");
918         }
919
920         // <SecurityKernel Critical="True" Ring="0">
921         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
922         // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
923         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
924         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
925         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
926         // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
927         // <ReferencesCritical Name="Field: m_safeAppChangedEvent" Ring="1" />
928         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
929         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_APPLICATIONToPeerApplication(System.Net.PeerToPeer.Collaboration.PEER_APPLICATION):System.Net.PeerToPeer.Collaboration.PeerApplication" Ring="1" />
930         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
931         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
932         // </SecurityKernel>
933         [System.Security.SecurityCritical]
934         private void ApplicationChangedCallback(object state, bool timedOut)
935         {
936             SafeCollabData eventData = null;
937             int errorCode = 0;
938
939             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ApplicationChangedCallback() called.");
940
941             while (true)
942             {
943                 ApplicationChangedEventArgs appChangedArgs = null;
944                 
945                 //
946                 // Get the event data for the fired event
947                 //
948                 try
949                 {
950                     lock (LockAppChangedEvent){
951                         if (m_safeAppChangedEvent.IsInvalid) return;
952                         errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeAppChangedEvent,
953                                                                                      out eventData);
954                     }
955                     
956                     if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
957                         break;
958                     else if (errorCode != 0){
959                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
960                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetApplicationChangedDataFailed), errorCode);
961                     }
962
963                     PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
964                                                                                                 typeof(PEER_COLLAB_EVENT_DATA));
965                     if (ped.eventType == PeerCollabEventType.EndPointApplicationChanged){
966                         PEER_EVENT_APPLICATION_CHANGED_DATA appData = ped.applicationChangedData;
967                         PEER_APPLICATION pa = (PEER_APPLICATION)Marshal.PtrToStructure(appData.pApplication, typeof(PEER_APPLICATION));
968
969                         PeerApplication peerApplication = CollaborationHelperFunctions.ConvertPEER_APPLICATIONToPeerApplication(pa); ;
970
971                         PeerContact peerContact = null;
972                         PeerEndPoint peerEndPoint = null;
973
974                         if (appData.pContact != IntPtr.Zero){
975                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(appData.pContact, typeof(PEER_CONTACT));
976                             peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
977                         }
978
979                         if (appData.pEndPoint != IntPtr.Zero){
980                             PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(appData.pEndPoint, typeof(PEER_ENDPOINT));
981                             peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
982                         }
983
984                         appChangedArgs = new ApplicationChangedEventArgs(peerEndPoint,
985                                                                 peerContact,
986                                                                 appData.changeType,
987                                                                 peerApplication);
988                     }
989                 }
990                 finally{
991                     if(eventData != null) eventData.Dispose();
992                 }
993
994                 //
995                 // Fire the callback with the marshalled event args data
996                 //
997
998                 EventHandler<ApplicationChangedEventArgs> handlerCopy = m_applicationChanged;
999
1000                 if ((appChangedArgs != null) && (handlerCopy != null)){
1001                     if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
1002                         SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, appChangedArgs });
1003                     else
1004                         handlerCopy(this, appChangedArgs);
1005                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the application changed event callback.");
1006                 }
1007             }
1008             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ApplicationChangedCallback().");
1009         }
1010         
1011         private event EventHandler<ObjectChangedEventArgs> m_objectChanged;
1012         public event EventHandler<ObjectChangedEventArgs> ObjectChanged
1013         {
1014             // <SecurityKernel Critical="True" Ring="1">
1015             // <ReferencesCritical Name="Method: AddObjectChangedEvent(EventHandler`1<System.Net.PeerToPeer.Collaboration.ObjectChangedEventArgs>):Void" Ring="1" />
1016             // </SecurityKernel>
1017             [System.Security.SecurityCritical]
1018             add
1019             {
1020                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1021                 
1022                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1023
1024                 AddObjectChangedEvent(value);
1025             }
1026             // <SecurityKernel Critical="True" Ring="2">
1027             // <ReferencesCritical Name="Method: RemoveObjectChangedEvent(EventHandler`1<System.Net.PeerToPeer.Collaboration.ObjectChangedEventArgs>):Void" Ring="2" />
1028             // </SecurityKernel>
1029             [System.Security.SecurityCritical]
1030             remove
1031             {
1032                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1033                 
1034                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1035
1036                 RemoveObjectChangedEvent(value);
1037             }
1038         }
1039
1040         #region Object changed event variables
1041         private object m_lockObjChangedEvent;
1042         private object LockObjChangedEvent
1043         {
1044             get{
1045                 if (m_lockObjChangedEvent == null){
1046                     object o = new object();
1047                     Interlocked.CompareExchange(ref m_lockObjChangedEvent, o, null);
1048                 }
1049                 return m_lockObjChangedEvent;
1050             }
1051         }
1052         private RegisteredWaitHandle m_regObjChangedWaitHandle;
1053         private AutoResetEvent m_objChangedEvent;
1054         private SafeCollabEvent m_safeObjChangedEvent;
1055         #endregion
1056
1057         // <SecurityKernel Critical="True" Ring="0">
1058         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabRegisterEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_COLLAB_EVENT_REGISTRATION&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&):System.Int32" />
1059         // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
1060         // <ReferencesCritical Name="Method: ObjectChangedCallback(Object, Boolean):Void" Ring="1" />
1061         // <ReferencesCritical Name="Field: m_safeObjChangedEvent" Ring="1" />
1062         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1063         // </SecurityKernel>
1064         [System.Security.SecurityCritical]
1065         private void AddObjectChangedEvent(EventHandler<ObjectChangedEventArgs> callback)
1066         {
1067             //
1068             // Register a wait handle if one has not been registered already
1069             //
1070
1071             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChangedEvent() called.");
1072
1073             lock (LockObjChangedEvent){
1074                 if (m_objectChanged == null){
1075
1076                     m_objChangedEvent = new AutoResetEvent(false);
1077
1078                     //
1079                     // Register callback with a wait handle
1080                     //
1081                     
1082                     m_regObjChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(m_objChangedEvent, //Event that triggers the callback
1083                                             new WaitOrTimerCallback(ObjectChangedCallback), //callback to be called 
1084                                             null, //state to be passed
1085                                             -1,   //Timeout - aplicable only for timers
1086                                             false //call us everytime the event is set
1087                                             );
1088                     PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
1089                     pcer.eventType = PeerCollabEventType.EndPointObjectChanged;
1090                     pcer.pInstance = IntPtr.Zero;
1091
1092                     //
1093                     // Register event with collab
1094                     //
1095
1096                     int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
1097                                                                         m_objChangedEvent.SafeWaitHandle,
1098                                                                         1,
1099                                                                         ref pcer,
1100                                                                         out m_safeObjChangedEvent);
1101                     if (errorCode != 0){
1102                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
1103                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ObjectChangedRegFailed), errorCode);
1104                     }
1105                 }
1106                 m_objectChanged += callback;
1107             }
1108
1109             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChanged() successful.");
1110         }
1111
1112         // <SecurityKernel Critical="True" Ring="1">
1113         // <ReferencesCritical Name="Field: m_safeObjChangedEvent" Ring="1" />
1114         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
1115         // </SecurityKernel>
1116         [System.Security.SecurityCritical]
1117         private void RemoveObjectChangedEvent(EventHandler<ObjectChangedEventArgs> callback)
1118         {
1119             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() called.");
1120             
1121             lock (LockObjChangedEvent){
1122                 m_objectChanged -= callback;
1123                 if (m_objectChanged == null){
1124                     CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle,
1125                                                                 ref m_safeObjChangedEvent,
1126                                                                 ref m_objChangedEvent);
1127                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful.");
1128                 }
1129             }
1130
1131             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "RemoveObjectChangedEvent() successful.");
1132         }
1133
1134         // <SecurityKernel Critical="True" Ring="0">
1135         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetEventData(System.Net.PeerToPeer.Collaboration.SafeCollabEvent,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
1136         // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
1137         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
1138         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
1139         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1140         // <ReferencesCritical Name="Local eventData of type: SafeCollabData" Ring="1" />
1141         // <ReferencesCritical Name="Field: m_safeObjChangedEvent" Ring="1" />
1142         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1143         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_OBJECTToPeerObject(System.Net.PeerToPeer.Collaboration.PEER_OBJECT):System.Net.PeerToPeer.Collaboration.PeerObject" Ring="1" />
1144         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(System.Net.PeerToPeer.Collaboration.PEER_ENDPOINT):System.Net.PeerToPeer.Collaboration.PeerEndPoint" Ring="1" />
1145         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
1146         // </SecurityKernel>
1147         [System.Security.SecurityCritical]
1148         private void ObjectChangedCallback(object state, bool timedOut)
1149         {
1150             SafeCollabData eventData = null;
1151             int errorCode = 0;
1152
1153             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "ObjectChangedCallback() called.");
1154
1155             while (true)
1156             {
1157                 ObjectChangedEventArgs objectChangedArgs = null;
1158
1159                 //
1160                 // Get the event data for the fired event
1161                 //
1162                 try{
1163                     lock (LockObjChangedEvent){
1164                         if (m_safeObjChangedEvent.IsInvalid) return;
1165                         errorCode = UnsafeCollabNativeMethods.PeerCollabGetEventData(m_safeObjChangedEvent,
1166                                                                                      out eventData);
1167                     }
1168                     if (errorCode == UnsafeCollabReturnCodes.PEER_S_NO_EVENT_DATA)
1169                         break;
1170                     else if (errorCode != 0){
1171                         Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetEventData returned with errorcode {0}", errorCode);
1172                         throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetObjectChangedDataFailed), errorCode);
1173                     }
1174
1175                     PEER_COLLAB_EVENT_DATA ped = (PEER_COLLAB_EVENT_DATA)Marshal.PtrToStructure(eventData.DangerousGetHandle(),
1176                                                                                                 typeof(PEER_COLLAB_EVENT_DATA));
1177                     
1178                     if (ped.eventType == PeerCollabEventType.EndPointObjectChanged){
1179                         PEER_EVENT_OBJECT_CHANGED_DATA objData = ped.objectChangedData;
1180                         PEER_OBJECT po = (PEER_OBJECT)Marshal.PtrToStructure(objData.pObject, typeof(PEER_OBJECT));
1181
1182                         PeerObject peerObject = CollaborationHelperFunctions.ConvertPEER_OBJECTToPeerObject(po);
1183
1184                         PeerContact peerContact = null;
1185                         PeerEndPoint peerEndPoint = null;
1186
1187                         if (objData.pContact != IntPtr.Zero){
1188                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(objData.pContact, typeof(PEER_CONTACT));
1189                             peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
1190                         }
1191
1192                         if (objData.pEndPoint != IntPtr.Zero){
1193                             PEER_ENDPOINT pe = (PEER_ENDPOINT)Marshal.PtrToStructure(objData.pEndPoint, typeof(PEER_ENDPOINT));
1194                             peerEndPoint = CollaborationHelperFunctions.ConvertPEER_ENDPOINTToPeerEndPoint(pe);
1195                         }
1196
1197                         objectChangedArgs = new ObjectChangedEventArgs(peerEndPoint,
1198                                                                                                 peerContact,
1199                                                                                                 objData.changeType,
1200                                                                                                 peerObject);
1201                     }
1202                 }
1203                 finally{
1204                     if(eventData != null) eventData.Dispose();
1205                 }
1206  
1207                 //
1208                 // Fire the callback with the marshalled event args data
1209                 //
1210
1211                 EventHandler<ObjectChangedEventArgs> handlerCopy = m_objectChanged;
1212
1213                 if ((objectChangedArgs != null) && (handlerCopy != null)){
1214                     if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
1215                         SynchronizingObject.BeginInvoke(handlerCopy, new object[] { this, objectChangedArgs });
1216                     else
1217                         handlerCopy(this, objectChangedArgs);
1218                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the object changed event callback.");
1219                 }
1220             }
1221             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving ObjectChangedCallback().");
1222         }
1223
1224         //
1225         // Grabs all the contacts from the users windows address book
1226         //
1227         // <SecurityKernel Critical="True" Ring="0">
1228         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabEnumContacts(System.Net.PeerToPeer.Collaboration.SafeCollabEnum&):System.Int32" />
1229         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerGetItemCount(System.Net.PeerToPeer.Collaboration.SafeCollabEnum,System.UInt32&):System.Int32" />
1230         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerGetNextItem(System.Net.PeerToPeer.Collaboration.SafeCollabEnum,System.UInt32&,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
1231         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
1232         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
1233         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1234         // <UsesUnsafeCode Name="Local pContacts of type: IntPtr*" />
1235         // <UsesUnsafeCode Name="Method: IntPtr.op_Explicit(System.IntPtr):System.Void*" />
1236         // <ReferencesCritical Name="Local handlePeerEnum of type: SafeCollabEnum" Ring="1" />
1237         // <ReferencesCritical Name="Local contactArray of type: SafeCollabData" Ring="1" />
1238         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1239         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
1240         // </SecurityKernel>
1241         [System.Security.SecurityCritical]
1242         public PeerContactCollection GetContacts()
1243         {
1244             PeerContactCollection peerContactColl = new PeerContactCollection();
1245             SafeCollabEnum handlePeerEnum = null;
1246             UInt32 contactCount = 0;
1247             int errorCode = 0;
1248
1249             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1250             
1251             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1252
1253             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering GetContacts()");
1254
1255             try{
1256                 //
1257                 // Get contacts array from native
1258                 //
1259                 
1260                 errorCode = UnsafeCollabNativeMethods.PeerCollabEnumContacts(out handlePeerEnum);
1261                 if (errorCode != 0){
1262                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabEnumContacts returned with errorcode {0}", errorCode);
1263                     throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
1264                 }
1265
1266                 errorCode = UnsafeCollabNativeMethods.PeerGetItemCount(handlePeerEnum, ref contactCount);
1267                 if (errorCode != 0){
1268                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetItemCount returned with errorcode {0}", errorCode);
1269                     throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
1270                 }
1271
1272                 if (contactCount == 0){
1273                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contacts found. \nLeaving GetContacts()");
1274                     return peerContactColl;
1275                 }
1276                 unsafe{
1277                     SafeCollabData contactArray = null;
1278                     try{
1279                         errorCode = UnsafeCollabNativeMethods.PeerGetNextItem(handlePeerEnum, ref contactCount, out contactArray);
1280                         if (errorCode != 0){
1281                             Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerGetNextItem returned with errorcode {0}", errorCode);
1282                             throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactsFailed), errorCode);
1283                         }
1284
1285                         //
1286                         // Loop through the contacts array to build PeerContact collection
1287                         //
1288
1289                         IntPtr pPEER_CONTACT = contactArray.DangerousGetHandle();
1290                         IntPtr* pContacts = (IntPtr*)pPEER_CONTACT;
1291                         for (ulong i = 0; i < contactCount; i++){
1292                             IntPtr pContactPtr = (IntPtr)pContacts[i];
1293                             PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(pContactPtr, typeof(PEER_CONTACT));
1294
1295                             PeerContact peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
1296                             peerContactColl.Add(peerContact);
1297                         }
1298                     }
1299                     finally{
1300                         contactArray.Dispose();
1301                     }
1302                 }
1303             }
1304             finally{
1305                 handlePeerEnum.Dispose();
1306             }
1307
1308             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
1309                 "Returning collections with {0} contacts. \nLeaving GetContacts()");
1310
1311             return peerContactColl;
1312         }
1313
1314         //
1315         // Gets specific contact from the users windows address book
1316         //
1317         // <SecurityKernel Critical="True" Ring="0">
1318         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabGetContact(System.String,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
1319         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
1320         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
1321         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1322         // <ReferencesCritical Name="Local safeContact of type: SafeCollabData" Ring="1" />
1323         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1324         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
1325         // </SecurityKernel>
1326         [System.Security.SecurityCritical]
1327         public PeerContact GetContact(PeerName peerName)
1328         {
1329             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1330             
1331             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1332             if (peerName == null)
1333                 throw new ArgumentNullException("peerName");
1334
1335             int errorCode = 0;
1336             SafeCollabData safeContact = null;
1337             PeerContact peerContact = null;
1338
1339             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, 
1340                 "Entering GetContact() with peername {0}", peerName.ToString());
1341
1342             try{
1343                 errorCode = UnsafeCollabNativeMethods.PeerCollabGetContact(peerName.ToString(),
1344                                                                         out safeContact);
1345                 if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){
1346                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
1347                     throw new PeerToPeerException(SR.GetString(SR.Collab_ContactNotFound));
1348                 }
1349                 else if (errorCode != 0){
1350                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
1351                     throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_GetContactFailed), errorCode);
1352                 }
1353
1354                 if (!safeContact.DangerousGetHandle().Equals(IntPtr.Zero)){
1355                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Found contact.");
1356                     PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(safeContact.DangerousGetHandle(), typeof(PEER_CONTACT));
1357                     peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
1358                 }
1359                 else{
1360                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "No contact found.");
1361                 }
1362             }
1363             finally{
1364                 safeContact.Dispose();
1365             }
1366             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving GetContact()");
1367
1368             return peerContact;
1369         }
1370
1371         // <SecurityKernel Critical="True" Ring="0">
1372         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabQueryContactData(System.IntPtr,System.String&):System.Int32" />
1373         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabParseContact(System.String,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
1374         // <SatisfiesLinkDemand Name="GCHandle.Alloc(System.Object,System.Runtime.InteropServices.GCHandleType):System.Runtime.InteropServices.GCHandle" />
1375         // <SatisfiesLinkDemand Name="GCHandle.AddrOfPinnedObject():System.IntPtr" />
1376         // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
1377         // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
1378         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1379         // <SatisfiesLinkDemand Name="GCHandle.Free():System.Void" />
1380         // <ReferencesCritical Name="Local contact of type: SafeCollabData" Ring="1" />
1381         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1382         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT):System.Net.PeerToPeer.Collaboration.PeerContact" Ring="2" />
1383         // </SecurityKernel>
1384         [System.Security.SecurityCritical]
1385         public PeerContact CreateContact(PeerNearMe peerNearMe) 
1386         {
1387             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1388             
1389             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1390
1391             if (peerNearMe == null)
1392                 throw new ArgumentNullException("peerNearMe");
1393
1394             if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null))
1395                 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
1396
1397             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContact() with peernearme", peerNearMe.ToString());
1398
1399             PeerEndPoint peerEndPoint = peerNearMe.PeerEndPoints[0];
1400
1401             PEER_ENDPOINT pe = new PEER_ENDPOINT();
1402             pe.peerAddress = CollaborationHelperFunctions.ConvertIPEndpointToPEER_ADDRESS(peerEndPoint.EndPoint);
1403
1404             //
1405             // Pin all the data to pass to native
1406             //
1407             GCHandle pepName = new GCHandle();
1408
1409             if (peerEndPoint.Name != null){
1410                 pepName = GCHandle.Alloc(peerEndPoint.Name, GCHandleType.Pinned);
1411                 pe.pwzEndpointName = pepName.AddrOfPinnedObject();
1412             }
1413             
1414             GCHandle peerEP = GCHandle.Alloc(pe, GCHandleType.Pinned);
1415             IntPtr ptrPeerEP = peerEP.AddrOfPinnedObject();
1416
1417             string contactData = null;
1418             int errorCode = 0;
1419             
1420             //
1421             // Refresh end point data if it not subscribed
1422             //
1423             peerNearMe.RefreshData();
1424
1425             errorCode = UnsafeCollabNativeMethods.PeerCollabQueryContactData(ptrPeerEP, ref contactData);
1426             if (errorCode != 0){
1427                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
1428                 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode);
1429             }
1430
1431             SafeCollabData contact = null;
1432             PeerContact peerContact = null;
1433
1434             try{
1435                 errorCode = UnsafeCollabNativeMethods.PeerCollabParseContact(contactData, out contact);
1436                 if (errorCode != 0){
1437                     Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabGetContact returned with errorcode {0}", errorCode);
1438                     throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CreateContactFailed), errorCode);
1439                 }
1440
1441                 PEER_CONTACT pc = (PEER_CONTACT)Marshal.PtrToStructure(contact.DangerousGetHandle(), typeof(PEER_CONTACT));
1442                 peerContact = CollaborationHelperFunctions.ConvertPEER_CONTACTToPeerContact(pc);
1443                 
1444                 //
1445                 // Mark it as just created and add the xml. This is used when adding the contact or getting
1446                 // contact xml when contact is not added
1447                 //
1448                 peerContact.JustCreated = true;
1449                 peerContact.ContactXml = contactData;
1450             }
1451             finally{
1452                 if (contact != null) contact.Dispose();
1453                 pepName.Free();
1454                 peerEP.Free();
1455             }
1456             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContact().");
1457
1458             return peerContact;
1459         }
1460
1461         SendOrPostCallback OnCreateContactCompletedDelegate;
1462         object m_createContactAsyncListLock;
1463         object CreateContactAsyncListLock
1464         {
1465             get{
1466                 if (m_createContactAsyncListLock == null){
1467                     object o = new object();
1468                     Interlocked.CompareExchange(ref m_createContactAsyncListLock, o, null);
1469                 }
1470                 return m_createContactAsyncListLock;
1471             }
1472         }
1473         Dictionary<object, AsyncOperation> m_createContactAsyncList = new Dictionary<object, AsyncOperation>();
1474
1475         private event EventHandler<CreateContactCompletedEventArgs> m_createContactCompleted;
1476         public event EventHandler<CreateContactCompletedEventArgs> CreateContactCompleted
1477         {
1478             add
1479             {
1480                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1481                 
1482                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1483
1484                 m_createContactCompleted += value;
1485             }
1486             remove
1487             {
1488                 if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1489                 
1490                 PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1491
1492                 m_createContactCompleted -= value;
1493             }
1494         }
1495
1496
1497         //
1498         // Stores state to pass to the create contact async helper
1499         //
1500         private class CreateContactAsyncState
1501         {
1502             PeerNearMe m_peerNearMe;
1503             Object m_userToken;
1504             internal CreateContactAsyncState(PeerNearMe peerNearMe, Object userToken){
1505                 m_peerNearMe = peerNearMe;
1506                 m_userToken = userToken;
1507             }
1508             internal PeerNearMe PeerNearMe
1509             {
1510                 get { return m_peerNearMe; }
1511             }
1512             internal Object UserToken
1513             {
1514                 get { return m_userToken; }
1515             }
1516         }
1517
1518         public void CreateContactAsync(PeerNearMe peerNearMe, Object userToken)
1519         {
1520             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1521             
1522             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1523
1524             if (peerNearMe == null)
1525                 throw new ArgumentNullException("PeerNearMe");
1526
1527             if ((peerNearMe.PeerEndPoints == null) || (peerNearMe.PeerEndPoints.Count == 0) || (peerNearMe.PeerEndPoints[0].EndPoint == null))
1528                 throw new PeerToPeerException(SR.GetString(SR.Collab_NoEndpointFound));
1529
1530             if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
1531                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering CreateContactAsync() with token {0} and following peernearme" , userToken);
1532                 peerNearMe.TracePeerNearMe();
1533             }
1534
1535             //
1536             // Add to list of usertokens 
1537             //
1538             lock (CreateContactAsyncListLock){
1539                 if (m_createContactAsyncList.ContainsKey(userToken)){
1540                     throw new ArgumentException(SR.GetString(SR.DuplicateUserToken));
1541                 }
1542                 AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userToken);
1543                 m_createContactAsyncList[userToken] = asyncOp;
1544             }
1545
1546             ThreadPool.QueueUserWorkItem(new WaitCallback(CreateContactAsyncHelper), new CreateContactAsyncState(peerNearMe, userToken));
1547
1548             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Leaving CreateContactAsync().");
1549
1550         }
1551
1552         //
1553         // Used to create a contact async'ally
1554         //
1555         private void CreateContactAsyncHelper(object state)
1556         {
1557             Exception ex = null;
1558             PeerContact peerContact = null;
1559             CreateContactAsyncState createAsyncState = state as CreateContactAsyncState;
1560             PeerNearMe peerNearMe = createAsyncState.PeerNearMe;
1561             object userToken = createAsyncState.UserToken;
1562
1563             //
1564             // Call the sync version of createcontact
1565             //
1566             try{
1567                 peerContact = CreateContact(peerNearMe);
1568             }
1569             catch (ObjectDisposedException e){
1570                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message);
1571                 ex = e;
1572             }
1573             catch (PeerToPeerException e){
1574                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "CreateContactAsyncHelper caught error {0}", e.Message);
1575                 ex = e;
1576             }
1577
1578             CreateContactCompletedEventArgs createContactCompletedArgs;
1579             if (ex == null){
1580                 createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, null, false, userToken);
1581             }
1582             else{
1583                 createContactCompletedArgs = new CreateContactCompletedEventArgs(peerContact, ex, false, userToken);
1584             }
1585
1586             PrepareToRaiseCreateContactCompletedEvent(m_createContactAsyncList[userToken], createContactCompletedArgs);
1587         }
1588
1589         void OnCreateContactCompleted(CreateContactCompletedEventArgs e)
1590         {
1591             EventHandler<CreateContactCompletedEventArgs> handlerCopy = m_createContactCompleted;
1592             if (handlerCopy != null){
1593                 handlerCopy(this, e);
1594                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Fired the create contact completed event callback.");
1595             }
1596         }
1597
1598         void CreateContactCompletedWaitCallback(object operationState)
1599         {
1600             CreateContactCompletedEventArgs args = (CreateContactCompletedEventArgs) operationState;
1601             //
1602             // Remove from usertoken list
1603             //
1604             m_createContactAsyncList.Remove(args.UserState);
1605
1606             OnCreateContactCompleted(args);
1607         }
1608
1609         internal void PrepareToRaiseCreateContactCompletedEvent(AsyncOperation asyncOP, CreateContactCompletedEventArgs args)
1610         {
1611             asyncOP.PostOperationCompleted(OnCreateContactCompletedDelegate, args);
1612         }
1613
1614         //
1615         // Adds a contacts to the users windows address book
1616         //
1617         // <SecurityKernel Critical="True" Ring="0">
1618         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabAddContact(System.String,System.Net.PeerToPeer.Collaboration.SafeCollabData&):System.Int32" />
1619         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1620         // <ReferencesCritical Name="Local contact of type: SafeCollabData" Ring="1" />
1621         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1622         // </SecurityKernel>
1623         [System.Security.SecurityCritical]
1624         public void AddContact(PeerContact peerContact) 
1625         {
1626             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1627             
1628             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1629
1630             if (peerContact == null)
1631                 throw new ArgumentNullException("peerContact");
1632
1633             string contactXml = null;
1634
1635             if (peerContact.ContactXml == null){
1636                 try{
1637                     contactXml = peerContact.ToXml();
1638                 }
1639                 catch (PeerToPeerException e){ 
1640                     throw new PeerToPeerException(SR.GetString(SR.Collab_AddContactFailedNoXml), e.InnerException);
1641                 }
1642             }
1643             else{
1644                 contactXml = peerContact.ContactXml;
1645             }
1646
1647             if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
1648                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering AddContact() with following peercontact");
1649                 peerContact.TracePeerContact();
1650             }
1651
1652             SafeCollabData contact = null;
1653             int errorCode = 0;
1654
1655             try{
1656                 errorCode = UnsafeCollabNativeMethods.PeerCollabAddContact(contactXml, out contact);
1657             }
1658             finally{
1659                 if(contact != null) contact.Dispose();
1660             }
1661
1662             if (errorCode == UnsafeCollabReturnCodes.PEER_E_ALREADY_EXISTS){
1663                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}. Contact already exists.", errorCode);
1664                 throw new ArgumentException(SR.GetString(SR.Collab_AddContactFailed) + " " + SR.GetString(SR.Collab_ContactExists));
1665             }
1666             else if (errorCode != 0){
1667                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabAddContact returned with errorcode {0}", errorCode);
1668                 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_AddContactFailed), errorCode);
1669             }
1670
1671             peerContact.JustCreated = false;
1672             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1673                                     "Leaving AddContact() successfully.");
1674             
1675         }
1676
1677         //
1678         // Deletes a contact from the users windows address book
1679         //
1680         public void DeleteContact(PeerContact peerContact) 
1681         {
1682             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1683                             "Entering DeleteContact().");
1684
1685             if (peerContact == null)
1686                 throw new ArgumentNullException("peerContact");
1687
1688             DeleteContact(peerContact.PeerName);
1689             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1690                             "Leaving DeleteContact() successfully.");
1691
1692         }
1693
1694         //
1695         // Deletes a contact from the users windows address book
1696         //
1697         // <SecurityKernel Critical="True" Ring="0">
1698         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabDeleteContact(System.String):System.Int32" />
1699         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1700         // </SecurityKernel>
1701         [System.Security.SecurityCritical]
1702         public void DeleteContact(PeerName peerName)
1703         {
1704             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1705                         "Entering DeleteContact().");
1706
1707             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1708             
1709             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1710             if (peerName == null)
1711                 throw new ArgumentNullException("peerName");
1712
1713             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1714                         "Peername is {0}", peerName.ToString());
1715
1716             int errorCode = UnsafeCollabNativeMethods.PeerCollabDeleteContact(peerName.ToString());
1717
1718             if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){
1719                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
1720                 throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerName");
1721             } 
1722             else if (errorCode != 0){
1723                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabDeleteContact returned with errorcode {0}", errorCode);
1724                 throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_DeleteContactFailed), errorCode));
1725             }
1726             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1727                         "Leaving DeleteContact() successfully.");
1728         }
1729
1730         //
1731         // Updates a contact from the users windows address book
1732         //
1733         // <SecurityKernel Critical="True" Ring="0">
1734         // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabUpdateContact(System.Net.PeerToPeer.Collaboration.PEER_CONTACT&):System.Int32" />
1735         // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
1736         // <ReferencesCritical Name="Local safeCredentials of type: SafeCollabMemory" Ring="1" />
1737         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(System.Net.PeerToPeer.Collaboration.PeerContact,System.Net.PeerToPeer.Collaboration.SafeCollabMemory&):System.Net.PeerToPeer.Collaboration.PEER_CONTACT" Ring="1" />
1738         // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
1739         // </SecurityKernel>
1740         [System.Security.SecurityCritical]
1741         public void UpdateContact(PeerContact peerContact) 
1742         {
1743             if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName);
1744             
1745             PeerCollaborationPermission.UnrestrictedPeerCollaborationPermission.Demand();
1746             if (peerContact == null)
1747                 throw new ArgumentNullException("peerContact");
1748
1749             if (peerContact.PeerName == null)
1750                 throw new ArgumentException(SR.GetString(SR.Collab_NoPeerNameInContact));
1751
1752             if (Logging.P2PTraceSource.Switch.ShouldTrace(TraceEventType.Information)){
1753                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Entering UpdateContact() with following peercontact");
1754                 peerContact.TracePeerContact();
1755             }
1756
1757             SafeCollabMemory safeCredentials = null;
1758             int errorCode = 0;
1759
1760             try{
1761                 PEER_CONTACT pc = CollaborationHelperFunctions.ConvertPeerContactToPEER_CONTACT(peerContact, ref safeCredentials);
1762
1763                 errorCode = UnsafeCollabNativeMethods.PeerCollabUpdateContact(ref pc);
1764             }
1765             finally{
1766                 if (safeCredentials != null) safeCredentials.Dispose();
1767             }
1768
1769             if (errorCode == UnsafeCollabReturnCodes.PEER_E_CONTACT_NOT_FOUND){
1770                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "Contact not found in Contact Manager");
1771                 throw new ArgumentException(SR.GetString(SR.Collab_ContactNotFound), "peerContact");
1772             }
1773             else if (errorCode != 0){
1774                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabUpdateContact returned with errorcode {0}", errorCode);
1775                 throw (PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_UpdateContactFailed), errorCode));
1776             }
1777             Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0,
1778                                         "Leaving UpdateContact() successfully.");
1779         }
1780
1781         private bool m_Disposed;
1782
1783         // <SecurityKernel Critical="True" Ring="2">
1784         // <ReferencesCritical Name="Method: Dispose(Boolean):Void" Ring="2" />
1785         // </SecurityKernel>
1786         [System.Security.SecurityCritical]
1787         public void Dispose()
1788         {
1789             Dispose(true);
1790             GC.SuppressFinalize(this);
1791         }
1792
1793         // <SecurityKernel Critical="True" Ring="1">
1794         // <ReferencesCritical Name="Field: m_safeSubLstChangedEvent" Ring="1" />
1795         // <ReferencesCritical Name="Method: CollaborationHelperFunctions.CleanEventVars(System.Threading.RegisteredWaitHandle&,System.Net.PeerToPeer.Collaboration.SafeCollabEvent&,System.Threading.AutoResetEvent&):System.Void" Ring="1" />
1796         // <ReferencesCritical Name="Field: m_safeNameChangedEvent" Ring="1" />
1797         // <ReferencesCritical Name="Field: m_safePresenceChangedEvent" Ring="1" />
1798         // <ReferencesCritical Name="Field: m_safeAppChangedEvent" Ring="1" />
1799         // <ReferencesCritical Name="Field: m_safeObjChangedEvent" Ring="1" />
1800         // </SecurityKernel>
1801         [System.Security.SecurityCritical]
1802         void Dispose(bool disposing)
1803         {
1804             if (!m_Disposed){
1805                 CollaborationHelperFunctions.CleanEventVars(ref m_regSubLstChangedWaitHandle,
1806                                                             ref m_safeSubLstChangedEvent,
1807                                                             ref m_subLstChangedEvent);
1808                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean SubscriptionListChanged variables successful.");
1809                 
1810                 CollaborationHelperFunctions.CleanEventVars(ref m_regNameChangedWaitHandle,
1811                                                             ref m_safeNameChangedEvent,
1812                                                             ref m_nameChangedEvent);
1813                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean NameChanged variables successful.");
1814                 
1815                 CollaborationHelperFunctions.CleanEventVars(ref m_regPresenceChangedWaitHandle,
1816                                                             ref m_safePresenceChangedEvent,
1817                                                             ref m_presenceChangedEvent);
1818                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean PresenceChanged variables successful.");
1819
1820                 CollaborationHelperFunctions.CleanEventVars(ref m_regAppChangedWaitHandle,
1821                                                             ref m_safeAppChangedEvent,
1822                                                             ref m_appChangedEvent);
1823                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ApplicationChanged variables successful.");
1824
1825                 CollaborationHelperFunctions.CleanEventVars(ref m_regObjChangedWaitHandle,
1826                                                             ref m_safeObjChangedEvent,
1827                                                             ref m_objChangedEvent);
1828                 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "Clean ObjectChanged variables successful.");
1829
1830                 m_Disposed = true;
1831             }
1832         }
1833     }
1834 }