1 //------------------------------------------------------------------------------
2 // <copyright file="CollaborationHelperFunctions.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 using System.Security.Permissions;
9 namespace System.Net.PeerToPeer.Collaboration
12 using System.Collections.ObjectModel;
13 using System.Runtime.InteropServices;
14 using System.Net.Mail;
15 using System.Security.Cryptography.X509Certificates;
16 using System.Diagnostics;
17 using System.Threading;
20 /// This class contains some of the common functions needed for peer
23 internal static class CollaborationHelperFunctions
25 private static volatile bool s_Initialized;
26 private static object s_LockInitialized = new object();
27 private const short c_CollabVersion = 0x0001;
30 // Initialise windows collab. This has to be called before any collab operation
32 // <SecurityKernel Critical="True" Ring="0">
33 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabStartup(System.Int16):System.Int32" />
34 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
36 [System.Security.SecurityCritical]
37 internal static void Initialize()
40 lock (s_LockInitialized){
42 if(!PeerToPeerOSHelper.SupportsP2P)
43 throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable));
44 int errorCode = UnsafeCollabNativeMethods.PeerCollabStartup(c_CollabVersion);
46 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabStartup returned with errorcode {0}", errorCode);
47 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_StartupFailed), errorCode);
56 // Converts Guid class to GUID structure that we can pass into native
58 internal static GUID ConvertGuidToGUID(Guid guid)
60 GUID newGuid = new GUID();
63 byte[] guidBytes = guid.ToByteArray();
64 string guidString = guid.ToString();
67 int endVal = guidString.IndexOf('-');
68 newGuid.data1 = (uint)(Convert.ToUInt32(guidString.Substring(startVal, endVal - startVal), 16));
69 startVal = endVal + 1;
70 endVal = guidString.IndexOf('-', endVal + 1);
71 newGuid.data2 = (ushort)(Convert.ToUInt16(guidString.Substring(startVal, endVal - startVal), 16));
72 startVal = endVal + 1;
73 endVal = guidString.IndexOf('-', endVal + 1);
74 newGuid.data3 = (ushort)(Convert.ToUInt16(guidString.Substring(startVal, endVal - startVal), 16));
75 newGuid.data4 = guidBytes[8];
76 newGuid.data5 = guidBytes[9];
77 newGuid.data6 = guidBytes[10];
78 newGuid.data7 = guidBytes[11];
79 newGuid.data8 = guidBytes[12];
80 newGuid.data9 = guidBytes[13];
81 newGuid.data10 = guidBytes[14];
82 newGuid.data11 = guidBytes[15];
88 // Converts native GUID structure to managed Guid class
90 internal static Guid ConvertGUIDToGuid(GUID guid)
92 byte[] bytes = new byte[8];
93 bytes[0] = guid.data4;
94 bytes[1] = guid.data5;
95 bytes[2] = guid.data6;
96 bytes[3] = guid.data7;
97 bytes[4] = guid.data8;
98 bytes[5] = guid.data9;
99 bytes[6] = guid.data10;
100 bytes[7] = guid.data11;
102 return new Guid((int)guid.data1, (short)guid.data2, (short)guid.data3, bytes);
106 // Converts native PEER_CONTACT to PeerContact class
108 // <SecurityKernel Critical="True" Ring="1">
109 // <ReferencesCritical Name="Method: ConvertPEER_CONTACTToPeerContact(PEER_CONTACT, Boolean):PeerContact" Ring="1" />
111 [System.Security.SecurityCritical]
112 internal static PeerContact ConvertPEER_CONTACTToPeerContact(PEER_CONTACT pc)
114 return ConvertPEER_CONTACTToPeerContact(pc, false);
117 // <SecurityKernel Critical="True" Ring="0">
118 // <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
119 // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
120 // <SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
121 // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
122 // <SatisfiesLinkDemand Name="X509Store..ctor(System.IntPtr)" />
123 // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
124 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.CertOpenStore(System.IntPtr,System.UInt32,System.IntPtr,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_DATA&):System.Net.PeerToPeer.Collaboration.SafeCertStore" />
125 // <ReferencesCritical Name="Local certHandle of type: SafeCertStore" Ring="1" />
126 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
127 // <ReferencesCritical Name="Method: PeerContact..ctor()" Ring="2" />
128 // <ReferencesCritical Name="Method: MyContact..ctor()" Ring="3" />
130 [System.Security.SecurityCritical]
131 internal static PeerContact ConvertPEER_CONTACTToPeerContact(PEER_CONTACT pc, bool isMyContact)
133 PeerContact peerContact = (isMyContact ? new MyContact(): new PeerContact());
134 peerContact.PeerName = new PeerName(pc.pwzPeerName);
135 peerContact.DisplayName = pc.pwzDisplayName;
136 peerContact.Nickname = pc.pwzNickname;
137 peerContact.EmailAddress = (pc.pwzEmailAddress != null) ? new MailAddress(pc.pwzEmailAddress) : null;
139 peerContact.SubscribeAllowed = pc.WatcherPermissions;
140 peerContact.IsSubscribed = (isMyContact ? true : pc.fWatch);
143 if (pc.credentials.cbData != 0){
144 data = new byte[pc.credentials.cbData];
145 Marshal.Copy(pc.credentials.pbData, data, 0, (int)pc.credentials.cbData);
150 SafeCertStore certHandle = UnsafeCollabNativeMethods.CertOpenStore(new IntPtr(/*CERT_STORE_PROV_PKCS7*/ 5),
151 0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
153 0x00000001/*CERT_STORE_NO_CRYPT_RELEASE_FLAG*/,
156 if (certHandle == null || certHandle.IsInvalid){
157 int win32ErrorCode = Marshal.GetLastWin32Error();
158 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CredentialsError), win32ErrorCode);
161 X509Store certStore = new X509Store(certHandle.DangerousGetHandle());
162 peerContact.Credentials = new X509Certificate2(certStore.Certificates[0]);
165 if(certHandle != null) certHandle.Dispose();
172 // <SecurityKernel Critical="True" Ring="0">
173 // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
174 // <SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
175 // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
176 // <SatisfiesLinkDemand Name="X509Store..ctor(System.IntPtr)" />
177 // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
178 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.CertOpenStore(System.IntPtr,System.UInt32,System.IntPtr,System.UInt32,System.IntPtr):System.Net.PeerToPeer.Collaboration.SafeCertStore" />
179 // <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.CertSaveStore(System.Net.PeerToPeer.Collaboration.SafeCertStore,System.UInt32,System.UInt32,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_DATA&,System.UInt32):System.Boolean" />
180 // <ReferencesCritical Name="Local certHandle of type: SafeCertStore" Ring="1" />
181 // <ReferencesCritical Name="Parameter safeCredentials of type: SafeCollabMemory" Ring="1" />
182 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
183 // <ReferencesCritical Name="Method: SafeCollabMemory..ctor(System.Int32)" Ring="1" />
185 [System.Security.SecurityCritical]
186 internal static PEER_CONTACT ConvertPeerContactToPEER_CONTACT(PeerContact peerContact, ref SafeCollabMemory safeCredentials)
188 PEER_CONTACT pc = new PEER_CONTACT();
190 pc.pwzDisplayName = peerContact.DisplayName;
191 pc.pwzEmailAddress = (peerContact.EmailAddress == null) ? null : peerContact.EmailAddress.ToString();
192 pc.pwzNickname = peerContact.Nickname;
193 pc.pwzPeerName = peerContact.PeerName.ToString();
194 pc.fWatch = peerContact.IsSubscribed;
195 pc.WatcherPermissions = peerContact.SubscribeAllowed;
196 PEER_DATA pd = new PEER_DATA();
198 if (peerContact.Credentials != null){
199 SafeCertStore certHandle = UnsafeCollabNativeMethods.CertOpenStore(new IntPtr(/*CERT_STORE_PROV_MEMORY*/ 2),
202 0x00002000/*CERT_STORE_CREATE_NEW_FLAG*/ | 0x00000001/*CERT_STORE_NO_CRYPT_RELEASE_FLAG*/,
205 if (certHandle == null || certHandle.IsInvalid){
206 int win32ErrorCode = Marshal.GetLastWin32Error();
207 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CredentialsError), win32ErrorCode);
211 X509Store certStore = new X509Store(certHandle.DangerousGetHandle());
212 certStore.Add(peerContact.Credentials as X509Certificate2);
213 bool returnCode = UnsafeCollabNativeMethods.CertSaveStore(certHandle,
214 0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
215 2 /*CERT_STORE_SAVE_AS_STORE*/,
216 2, /*CERT_STORE_SAVE_TO_MEMORY*/
220 if ((pd.cbData != 0) && (returnCode)){
221 safeCredentials = new SafeCollabMemory((int)pd.cbData);
222 pd.pbData = safeCredentials.DangerousGetHandle();
223 returnCode = UnsafeCollabNativeMethods.CertSaveStore(certHandle,
224 0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
225 2 /*CERT_STORE_SAVE_AS_STORE*/,
226 2, /*CERT_STORE_SAVE_TO_MEMORY*/
227 ref pd,// Clean up memory from here;
233 pd.pbData = IntPtr.Zero;
237 if (certHandle != null) certHandle.Dispose();
242 pd.pbData = IntPtr.Zero;
251 // Converts address bytes to a SOCKADDR_IN6 that can be passed into
254 internal static void ByteArrayToSin6Addr(byte[] addrBytes, ref SOCKADDR_IN6 sin6)
256 sin6.sin6_addr0 = addrBytes[0];
257 sin6.sin6_addr1 = addrBytes[1];
258 sin6.sin6_addr2 = addrBytes[2];
259 sin6.sin6_addr3 = addrBytes[3];
260 sin6.sin6_addr4 = addrBytes[4];
261 sin6.sin6_addr5 = addrBytes[5];
262 sin6.sin6_addr6 = addrBytes[6];
263 sin6.sin6_addr7 = addrBytes[7];
264 sin6.sin6_addr8 = addrBytes[8];
265 sin6.sin6_addr9 = addrBytes[9];
266 sin6.sin6_addr10 = addrBytes[10];
267 sin6.sin6_addr11 = addrBytes[11];
268 sin6.sin6_addr12 = addrBytes[12];
269 sin6.sin6_addr13 = addrBytes[13];
270 sin6.sin6_addr14 = addrBytes[14];
271 sin6.sin6_addr15 = addrBytes[15];
275 // Converts native structure PEER_PEOPLE_NEAR_ME to managed PeerNearMe class
277 // <SecurityKernel Critical="True" Ring="0">
278 // <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
279 // <ReferencesCritical Name="Method: ConvertPEER_ENDPOINTToPeerEndPoint(PEER_ENDPOINT):PeerEndPoint" Ring="1" />
281 [System.Security.SecurityCritical]
282 internal static PeerNearMe PEER_PEOPLE_NEAR_METoPeerNearMe(PEER_PEOPLE_NEAR_ME ppnm)
284 PeerNearMe peerNearMe = new PeerNearMe();
285 peerNearMe.Id = CollaborationHelperFunctions.ConvertGUIDToGuid(ppnm.id);
286 peerNearMe.Nickname = Marshal.PtrToStringUni(ppnm.pwzNickname); ;
288 PEER_ENDPOINT pe = ppnm.endpoint;
289 PeerEndPoint peerEP = ConvertPEER_ENDPOINTToPeerEndPoint(pe);
290 peerNearMe.PeerEndPoints.Add(peerEP);
296 // Converts native PEER_OBJECT structure into PeerObject class
298 // <SecurityKernel Critical="True" Ring="0">
299 // <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
301 [System.Security.SecurityCritical]
302 internal static PeerObject ConvertPEER_OBJECTToPeerObject(PEER_OBJECT po)
306 if (po.data.cbData != 0){
307 data = new byte[po.data.cbData];
308 Marshal.Copy(po.data.pbData, data, 0, (int)po.data.cbData);
311 return new PeerObject(ConvertGUIDToGuid(po.guid), data, (PeerScope)po.dwPublicationScope);
315 // Converts native PEER_APPLICATION structure into PeerApplication class
318 // <SecurityKernel Critical="True" Ring="0">
319 // <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
320 // <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
322 [System.Security.SecurityCritical]
323 internal static PeerApplication ConvertPEER_APPLICATIONToPeerApplication(PEER_APPLICATION pa)
327 if (pa.data.cbData != 0){
328 data = new byte[pa.data.cbData];
329 Marshal.Copy(pa.data.pbData, data, 0, (int)pa.data.cbData);
332 return new PeerApplication( ConvertGUIDToGuid(pa.guid),
333 Marshal.PtrToStringUni(pa.pwzDescription),
335 null, null, PeerScope.None);
339 // Converts native PEER_ENDPOINT structure into PeerEndPoint class
342 // <SecurityKernel Critical="True" Ring="0">
343 // <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
345 [System.Security.SecurityCritical]
346 internal static PeerEndPoint ConvertPEER_ENDPOINTToPeerEndPoint(PEER_ENDPOINT pe)
349 byte[] addrBytes = new byte[]{ pe.peerAddress.sin6.sin6_addr0, pe.peerAddress.sin6.sin6_addr1,
350 pe.peerAddress.sin6.sin6_addr2, pe.peerAddress.sin6.sin6_addr3,
351 pe.peerAddress.sin6.sin6_addr4, pe.peerAddress.sin6.sin6_addr5,
352 pe.peerAddress.sin6.sin6_addr6, pe.peerAddress.sin6.sin6_addr7,
353 pe.peerAddress.sin6.sin6_addr8, pe.peerAddress.sin6.sin6_addr9,
354 pe.peerAddress.sin6.sin6_addr10, pe.peerAddress.sin6.sin6_addr11,
355 pe.peerAddress.sin6.sin6_addr12, pe.peerAddress.sin6.sin6_addr13,
356 pe.peerAddress.sin6.sin6_addr14, pe.peerAddress.sin6.sin6_addr15};
357 IPAddress IPAddr = new IPAddress(addrBytes, (long)pe.peerAddress.sin6.sin6_scope_id);
360 port = (ushort)IPAddress.NetworkToHostOrder((short)pe.peerAddress.sin6.sin6_port);
362 IPEndPoint IPEndPt = new IPEndPoint(IPAddr, port);
364 return new PeerEndPoint(IPEndPt, Marshal.PtrToStringUni(pe.pwzEndpointName));
368 // Converts IPEndpoint class into native PEER_ADDRESS structure
370 internal static PEER_ADDRESS ConvertIPEndpointToPEER_ADDRESS(IPEndPoint endPoint)
372 PEER_ADDRESS pa = new PEER_ADDRESS();
373 SOCKADDR_IN6 sin = new SOCKADDR_IN6();
374 sin.sin6_family = (ushort)endPoint.AddressFamily;
375 sin.sin6_flowinfo = 0; //
377 sin.sin6_port = (ushort)IPAddress.HostToNetworkOrder((short)endPoint.Port);
379 sin.sin6_scope_id = (uint)endPoint.Address.ScopeId;
380 CollaborationHelperFunctions.ByteArrayToSin6Addr(endPoint.Address.GetAddressBytes(), ref sin);
387 // Cleans up the registered handle and the wait event. Called under lock from events.
389 // <SecurityKernel Critical="True" Ring="0">
390 // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
391 // <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
392 // <ReferencesCritical Name="Parameter safeEvent of type: SafeCollabEvent" Ring="1" />
394 [System.Security.SecurityCritical]
395 [SecurityPermissionAttribute(SecurityAction.LinkDemand, UnmanagedCode = true)]
396 internal static void CleanEventVars(ref RegisteredWaitHandle waitHandle,
397 ref SafeCollabEvent safeEvent,
398 ref AutoResetEvent firedEvent)
400 if (waitHandle != null){
401 waitHandle.Unregister(null);
405 if ((safeEvent != null) && (!safeEvent.IsInvalid)){
409 if (firedEvent != null){
415 // <SecurityKernel Critical="True" Ring="0">
416 // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
417 // <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" />
418 // <ReferencesCritical Name="Parameter safePresenceChangedEvent of type: SafeCollabEvent" Ring="1" />
419 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
421 [System.Security.SecurityCritical]
422 internal static void AddMyPresenceChanged(EventHandler<PresenceChangedEventArgs> callback,
423 ref EventHandler<PresenceChangedEventArgs> presenceChanged,
424 object lockPresenceChangedEvent,
425 ref RegisteredWaitHandle regPresenceChangedWaitHandle,
426 ref AutoResetEvent presenceChangedEvent,
427 ref SafeCollabEvent safePresenceChangedEvent,
428 WaitOrTimerCallback PresenceChangedCallback)
431 // Register a wait handle if one has not been registered already
433 lock (lockPresenceChangedEvent){
434 if (presenceChanged == null){
436 presenceChangedEvent = new AutoResetEvent(false);
439 // Register callback with a wait handle
442 regPresenceChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(presenceChangedEvent, //Event that triggers the callback
443 PresenceChangedCallback, //callback to be called
444 null, //state to be passed
445 -1, //Timeout - aplicable only for timers
446 false //call us everytime the event is set
448 PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
449 pcer.eventType = PeerCollabEventType.MyPresenceChanged;
450 pcer.pInstance = IntPtr.Zero;
454 // Register event with collab
457 int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
458 presenceChangedEvent.SafeWaitHandle,
461 out safePresenceChangedEvent);
463 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
464 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PresenceChangedRegFailed), errorCode);
467 presenceChanged += callback;
470 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddMyPresenceChanged() successful.");
473 // <SecurityKernel Critical="True" Ring="0">
474 // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
475 // <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" />
476 // <ReferencesCritical Name="Parameter safeAppChangedEvent of type: SafeCollabEvent" Ring="1" />
477 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
479 [System.Security.SecurityCritical]
480 internal static void AddMyApplicationChanged(EventHandler<ApplicationChangedEventArgs> callback,
481 ref EventHandler<ApplicationChangedEventArgs> applicationChanged,
482 object lockAppChangedEvent,
483 ref RegisteredWaitHandle regAppChangedWaitHandle,
484 ref AutoResetEvent appChangedEvent,
485 ref SafeCollabEvent safeAppChangedEvent,
486 WaitOrTimerCallback ApplicationChangedCallback)
489 // Register a wait handle if one has not been registered already
491 lock (lockAppChangedEvent){
492 if (applicationChanged == null){
494 appChangedEvent = new AutoResetEvent(false);
497 // Register callback with a wait handle
500 regAppChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(appChangedEvent, //Event that triggers the callback
501 ApplicationChangedCallback, //callback to be called
502 null, //state to be passed
503 -1, //Timeout - aplicable only for timers
504 false //call us everytime the event is set
506 PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
508 pcer.eventType = PeerCollabEventType.MyApplicationChanged;
509 pcer.pInstance = IntPtr.Zero;
512 // Register event with collab
515 int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
516 appChangedEvent.SafeWaitHandle,
519 out safeAppChangedEvent);
521 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
522 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ApplicationChangedRegFailed), errorCode);
525 applicationChanged += callback;
528 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() successful.");
531 // <SecurityKernel Critical="True" Ring="0">
532 // <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
533 // <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" />
534 // <ReferencesCritical Name="Parameter safeObjChangedEvent of type: SafeCollabEvent" Ring="1" />
535 // <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
537 [System.Security.SecurityCritical]
538 internal static void AddMyObjectChanged(EventHandler<ObjectChangedEventArgs> callback,
539 ref EventHandler<ObjectChangedEventArgs> objectChanged,
540 object lockObjChangedEvent,
541 ref RegisteredWaitHandle regObjChangedWaitHandle,
542 ref AutoResetEvent objChangedEvent,
543 ref SafeCollabEvent safeObjChangedEvent,
544 WaitOrTimerCallback ObjectChangedCallback)
547 // Register a wait handle if one has not been registered already
549 lock (lockObjChangedEvent){
550 if (objectChanged == null){
552 objChangedEvent = new AutoResetEvent(false);
555 // Register callback with a wait handle
558 regObjChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(objChangedEvent, //Event that triggers the callback
559 ObjectChangedCallback, //callback to be called
560 null, //state to be passed
561 -1, //Timeout - aplicable only for timers
562 false //call us everytime the event is set
565 PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
566 pcer.eventType = PeerCollabEventType.MyObjectChanged;
567 pcer.pInstance = IntPtr.Zero;
571 // Register event with collab
574 int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
575 objChangedEvent.SafeWaitHandle,
578 out safeObjChangedEvent);
580 Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
581 throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ObjectChangedRegFailed), errorCode);
584 objectChanged += callback;
587 Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChanged() successful.");
591 internal static void ThrowIfInvitationResponseInvalid(PeerInvitationResponse response)
593 // throw an exception if the response from the native API was PEER_INVITATION_RESPONSE_ERROR
594 if (response.PeerInvitationResponseType < PeerInvitationResponseType.Declined ||
595 response.PeerInvitationResponseType > PeerInvitationResponseType.Expired)
597 throw new PeerToPeerException(SR.GetString(SR.Collab_InviteFailed));