602 lines
31 KiB
C#
602 lines
31 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="CollaborationHelperFunctions.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
using System.Security.Permissions;
|
|
|
|
namespace System.Net.PeerToPeer.Collaboration
|
|
{
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Runtime.InteropServices;
|
|
using System.Net.Mail;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
|
|
/// <summary>
|
|
/// This class contains some of the common functions needed for peer
|
|
/// collaboration
|
|
/// </summary>
|
|
internal static class CollaborationHelperFunctions
|
|
{
|
|
private static volatile bool s_Initialized;
|
|
private static object s_LockInitialized = new object();
|
|
private const short c_CollabVersion = 0x0001;
|
|
|
|
//
|
|
// Initialise windows collab. This has to be called before any collab operation
|
|
//
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.PeerCollabStartup(System.Int16):System.Int32" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static void Initialize()
|
|
{
|
|
if (!s_Initialized){
|
|
lock (s_LockInitialized){
|
|
if (!s_Initialized){
|
|
if(!PeerToPeerOSHelper.SupportsP2P)
|
|
throw new PlatformNotSupportedException(SR.GetString(SR.P2P_NotAvailable));
|
|
int errorCode = UnsafeCollabNativeMethods.PeerCollabStartup(c_CollabVersion);
|
|
if (errorCode != 0){
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabStartup returned with errorcode {0}", errorCode);
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_StartupFailed), errorCode);
|
|
}
|
|
s_Initialized = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Converts Guid class to GUID structure that we can pass into native
|
|
//
|
|
internal static GUID ConvertGuidToGUID(Guid guid)
|
|
{
|
|
GUID newGuid = new GUID();
|
|
|
|
if (guid != null){
|
|
byte[] guidBytes = guid.ToByteArray();
|
|
string guidString = guid.ToString();
|
|
|
|
int startVal = 0;
|
|
int endVal = guidString.IndexOf('-');
|
|
newGuid.data1 = (uint)(Convert.ToUInt32(guidString.Substring(startVal, endVal - startVal), 16));
|
|
startVal = endVal + 1;
|
|
endVal = guidString.IndexOf('-', endVal + 1);
|
|
newGuid.data2 = (ushort)(Convert.ToUInt16(guidString.Substring(startVal, endVal - startVal), 16));
|
|
startVal = endVal + 1;
|
|
endVal = guidString.IndexOf('-', endVal + 1);
|
|
newGuid.data3 = (ushort)(Convert.ToUInt16(guidString.Substring(startVal, endVal - startVal), 16));
|
|
newGuid.data4 = guidBytes[8];
|
|
newGuid.data5 = guidBytes[9];
|
|
newGuid.data6 = guidBytes[10];
|
|
newGuid.data7 = guidBytes[11];
|
|
newGuid.data8 = guidBytes[12];
|
|
newGuid.data9 = guidBytes[13];
|
|
newGuid.data10 = guidBytes[14];
|
|
newGuid.data11 = guidBytes[15];
|
|
}
|
|
return newGuid;
|
|
}
|
|
|
|
//
|
|
// Converts native GUID structure to managed Guid class
|
|
//
|
|
internal static Guid ConvertGUIDToGuid(GUID guid)
|
|
{
|
|
byte[] bytes = new byte[8];
|
|
bytes[0] = guid.data4;
|
|
bytes[1] = guid.data5;
|
|
bytes[2] = guid.data6;
|
|
bytes[3] = guid.data7;
|
|
bytes[4] = guid.data8;
|
|
bytes[5] = guid.data9;
|
|
bytes[6] = guid.data10;
|
|
bytes[7] = guid.data11;
|
|
|
|
return new Guid((int)guid.data1, (short)guid.data2, (short)guid.data3, bytes);
|
|
}
|
|
|
|
//
|
|
// Converts native PEER_CONTACT to PeerContact class
|
|
//
|
|
// <SecurityKernel Critical="True" Ring="1">
|
|
// <ReferencesCritical Name="Method: ConvertPEER_CONTACTToPeerContact(PEER_CONTACT, Boolean):PeerContact" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerContact ConvertPEER_CONTACTToPeerContact(PEER_CONTACT pc)
|
|
{
|
|
return ConvertPEER_CONTACTToPeerContact(pc, false);
|
|
}
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
|
// <SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
|
// <SatisfiesLinkDemand Name="X509Store..ctor(System.IntPtr)" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.CertOpenStore(System.IntPtr,System.UInt32,System.IntPtr,System.UInt32,System.Net.PeerToPeer.Collaboration.PEER_DATA&):System.Net.PeerToPeer.Collaboration.SafeCertStore" />
|
|
// <ReferencesCritical Name="Local certHandle of type: SafeCertStore" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerContact..ctor()" Ring="2" />
|
|
// <ReferencesCritical Name="Method: MyContact..ctor()" Ring="3" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerContact ConvertPEER_CONTACTToPeerContact(PEER_CONTACT pc, bool isMyContact)
|
|
{
|
|
PeerContact peerContact = (isMyContact ? new MyContact(): new PeerContact());
|
|
peerContact.PeerName = new PeerName(pc.pwzPeerName);
|
|
peerContact.DisplayName = pc.pwzDisplayName;
|
|
peerContact.Nickname = pc.pwzNickname;
|
|
peerContact.EmailAddress = (pc.pwzEmailAddress != null) ? new MailAddress(pc.pwzEmailAddress) : null;
|
|
if(!isMyContact)
|
|
peerContact.SubscribeAllowed = pc.WatcherPermissions;
|
|
peerContact.IsSubscribed = (isMyContact ? true : pc.fWatch);
|
|
byte[] data = null;
|
|
|
|
if (pc.credentials.cbData != 0){
|
|
data = new byte[pc.credentials.cbData];
|
|
Marshal.Copy(pc.credentials.pbData, data, 0, (int)pc.credentials.cbData);
|
|
}
|
|
|
|
if (data != null){
|
|
|
|
SafeCertStore certHandle = UnsafeCollabNativeMethods.CertOpenStore(new IntPtr(/*CERT_STORE_PROV_PKCS7*/ 5),
|
|
0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
|
|
IntPtr.Zero,
|
|
0x00000001/*CERT_STORE_NO_CRYPT_RELEASE_FLAG*/,
|
|
ref pc.credentials);
|
|
|
|
if (certHandle == null || certHandle.IsInvalid){
|
|
int win32ErrorCode = Marshal.GetLastWin32Error();
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CredentialsError), win32ErrorCode);
|
|
}
|
|
try{
|
|
X509Store certStore = new X509Store(certHandle.DangerousGetHandle());
|
|
peerContact.Credentials = new X509Certificate2(certStore.Certificates[0]);
|
|
}
|
|
finally{
|
|
if(certHandle != null) certHandle.Dispose();
|
|
}
|
|
}
|
|
|
|
return peerContact;
|
|
}
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
|
// <SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
|
|
// <SatisfiesLinkDemand Name="X509Store..ctor(System.IntPtr)" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
|
// <CallsSuppressUnmanagedCode Name="UnsafeCollabNativeMethods.CertOpenStore(System.IntPtr,System.UInt32,System.IntPtr,System.UInt32,System.IntPtr):System.Net.PeerToPeer.Collaboration.SafeCertStore" />
|
|
// <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" />
|
|
// <ReferencesCritical Name="Local certHandle of type: SafeCertStore" Ring="1" />
|
|
// <ReferencesCritical Name="Parameter safeCredentials of type: SafeCollabMemory" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// <ReferencesCritical Name="Method: SafeCollabMemory..ctor(System.Int32)" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PEER_CONTACT ConvertPeerContactToPEER_CONTACT(PeerContact peerContact, ref SafeCollabMemory safeCredentials)
|
|
{
|
|
PEER_CONTACT pc = new PEER_CONTACT();
|
|
|
|
pc.pwzDisplayName = peerContact.DisplayName;
|
|
pc.pwzEmailAddress = (peerContact.EmailAddress == null) ? null : peerContact.EmailAddress.ToString();
|
|
pc.pwzNickname = peerContact.Nickname;
|
|
pc.pwzPeerName = peerContact.PeerName.ToString();
|
|
pc.fWatch = peerContact.IsSubscribed;
|
|
pc.WatcherPermissions = peerContact.SubscribeAllowed;
|
|
PEER_DATA pd = new PEER_DATA();
|
|
|
|
if (peerContact.Credentials != null){
|
|
SafeCertStore certHandle = UnsafeCollabNativeMethods.CertOpenStore(new IntPtr(/*CERT_STORE_PROV_MEMORY*/ 2),
|
|
0,
|
|
IntPtr.Zero,
|
|
0x00002000/*CERT_STORE_CREATE_NEW_FLAG*/ | 0x00000001/*CERT_STORE_NO_CRYPT_RELEASE_FLAG*/,
|
|
IntPtr.Zero);
|
|
|
|
if (certHandle == null || certHandle.IsInvalid){
|
|
int win32ErrorCode = Marshal.GetLastWin32Error();
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_CredentialsError), win32ErrorCode);
|
|
}
|
|
|
|
try{
|
|
X509Store certStore = new X509Store(certHandle.DangerousGetHandle());
|
|
certStore.Add(peerContact.Credentials as X509Certificate2);
|
|
bool returnCode = UnsafeCollabNativeMethods.CertSaveStore(certHandle,
|
|
0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
|
|
2 /*CERT_STORE_SAVE_AS_STORE*/,
|
|
2, /*CERT_STORE_SAVE_TO_MEMORY*/
|
|
ref pd,
|
|
0);
|
|
|
|
if ((pd.cbData != 0) && (returnCode)){
|
|
safeCredentials = new SafeCollabMemory((int)pd.cbData);
|
|
pd.pbData = safeCredentials.DangerousGetHandle();
|
|
returnCode = UnsafeCollabNativeMethods.CertSaveStore(certHandle,
|
|
0x00000001/*X509_ASN_ENCODING*/| 0x00010000/*PKCS_7_ASN_ENCODING*/,
|
|
2 /*CERT_STORE_SAVE_AS_STORE*/,
|
|
2, /*CERT_STORE_SAVE_TO_MEMORY*/
|
|
ref pd,// Clean up memory from here;
|
|
0);
|
|
|
|
}
|
|
else{
|
|
pd.cbData = 0;
|
|
pd.pbData = IntPtr.Zero;
|
|
}
|
|
}
|
|
finally{
|
|
if (certHandle != null) certHandle.Dispose();
|
|
}
|
|
}
|
|
else{
|
|
pd.cbData = 0;
|
|
pd.pbData = IntPtr.Zero;
|
|
}
|
|
pc.credentials = pd;
|
|
|
|
return pc;
|
|
|
|
}
|
|
|
|
//
|
|
// Converts address bytes to a SOCKADDR_IN6 that can be passed into
|
|
// native
|
|
//
|
|
internal static void ByteArrayToSin6Addr(byte[] addrBytes, ref SOCKADDR_IN6 sin6)
|
|
{
|
|
sin6.sin6_addr0 = addrBytes[0];
|
|
sin6.sin6_addr1 = addrBytes[1];
|
|
sin6.sin6_addr2 = addrBytes[2];
|
|
sin6.sin6_addr3 = addrBytes[3];
|
|
sin6.sin6_addr4 = addrBytes[4];
|
|
sin6.sin6_addr5 = addrBytes[5];
|
|
sin6.sin6_addr6 = addrBytes[6];
|
|
sin6.sin6_addr7 = addrBytes[7];
|
|
sin6.sin6_addr8 = addrBytes[8];
|
|
sin6.sin6_addr9 = addrBytes[9];
|
|
sin6.sin6_addr10 = addrBytes[10];
|
|
sin6.sin6_addr11 = addrBytes[11];
|
|
sin6.sin6_addr12 = addrBytes[12];
|
|
sin6.sin6_addr13 = addrBytes[13];
|
|
sin6.sin6_addr14 = addrBytes[14];
|
|
sin6.sin6_addr15 = addrBytes[15];
|
|
}
|
|
|
|
//
|
|
// Converts native structure PEER_PEOPLE_NEAR_ME to managed PeerNearMe class
|
|
//
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
|
|
// <ReferencesCritical Name="Method: ConvertPEER_ENDPOINTToPeerEndPoint(PEER_ENDPOINT):PeerEndPoint" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerNearMe PEER_PEOPLE_NEAR_METoPeerNearMe(PEER_PEOPLE_NEAR_ME ppnm)
|
|
{
|
|
PeerNearMe peerNearMe = new PeerNearMe();
|
|
peerNearMe.Id = CollaborationHelperFunctions.ConvertGUIDToGuid(ppnm.id);
|
|
peerNearMe.Nickname = Marshal.PtrToStringUni(ppnm.pwzNickname); ;
|
|
|
|
PEER_ENDPOINT pe = ppnm.endpoint;
|
|
PeerEndPoint peerEP = ConvertPEER_ENDPOINTToPeerEndPoint(pe);
|
|
peerNearMe.PeerEndPoints.Add(peerEP);
|
|
|
|
return peerNearMe;
|
|
}
|
|
|
|
//
|
|
// Converts native PEER_OBJECT structure into PeerObject class
|
|
//
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerObject ConvertPEER_OBJECTToPeerObject(PEER_OBJECT po)
|
|
{
|
|
byte[] data = null;
|
|
|
|
if (po.data.cbData != 0){
|
|
data = new byte[po.data.cbData];
|
|
Marshal.Copy(po.data.pbData, data, 0, (int)po.data.cbData);
|
|
}
|
|
|
|
return new PeerObject(ConvertGUIDToGuid(po.guid), data, (PeerScope)po.dwPublicationScope);
|
|
}
|
|
|
|
//
|
|
// Converts native PEER_APPLICATION structure into PeerApplication class
|
|
//
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
|
|
// <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerApplication ConvertPEER_APPLICATIONToPeerApplication(PEER_APPLICATION pa)
|
|
{
|
|
byte[] data = null;
|
|
|
|
if (pa.data.cbData != 0){
|
|
data = new byte[pa.data.cbData];
|
|
Marshal.Copy(pa.data.pbData, data, 0, (int)pa.data.cbData);
|
|
}
|
|
|
|
return new PeerApplication( ConvertGUIDToGuid(pa.guid),
|
|
Marshal.PtrToStringUni(pa.pwzDescription),
|
|
data,
|
|
null, null, PeerScope.None);
|
|
}
|
|
|
|
//
|
|
// Converts native PEER_ENDPOINT structure into PeerEndPoint class
|
|
//
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="Marshal.PtrToStringUni(System.IntPtr):System.String" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static PeerEndPoint ConvertPEER_ENDPOINTToPeerEndPoint(PEER_ENDPOINT pe)
|
|
{
|
|
|
|
byte[] addrBytes = new byte[]{ pe.peerAddress.sin6.sin6_addr0, pe.peerAddress.sin6.sin6_addr1,
|
|
pe.peerAddress.sin6.sin6_addr2, pe.peerAddress.sin6.sin6_addr3,
|
|
pe.peerAddress.sin6.sin6_addr4, pe.peerAddress.sin6.sin6_addr5,
|
|
pe.peerAddress.sin6.sin6_addr6, pe.peerAddress.sin6.sin6_addr7,
|
|
pe.peerAddress.sin6.sin6_addr8, pe.peerAddress.sin6.sin6_addr9,
|
|
pe.peerAddress.sin6.sin6_addr10, pe.peerAddress.sin6.sin6_addr11,
|
|
pe.peerAddress.sin6.sin6_addr12, pe.peerAddress.sin6.sin6_addr13,
|
|
pe.peerAddress.sin6.sin6_addr14, pe.peerAddress.sin6.sin6_addr15};
|
|
IPAddress IPAddr = new IPAddress(addrBytes, (long)pe.peerAddress.sin6.sin6_scope_id);
|
|
ushort port;
|
|
unchecked{
|
|
port = (ushort)IPAddress.NetworkToHostOrder((short)pe.peerAddress.sin6.sin6_port);
|
|
}
|
|
IPEndPoint IPEndPt = new IPEndPoint(IPAddr, port);
|
|
|
|
return new PeerEndPoint(IPEndPt, Marshal.PtrToStringUni(pe.pwzEndpointName));
|
|
}
|
|
|
|
//
|
|
// Converts IPEndpoint class into native PEER_ADDRESS structure
|
|
//
|
|
internal static PEER_ADDRESS ConvertIPEndpointToPEER_ADDRESS(IPEndPoint endPoint)
|
|
{
|
|
PEER_ADDRESS pa = new PEER_ADDRESS();
|
|
SOCKADDR_IN6 sin = new SOCKADDR_IN6();
|
|
sin.sin6_family = (ushort)endPoint.AddressFamily;
|
|
sin.sin6_flowinfo = 0; //
|
|
unchecked{
|
|
sin.sin6_port = (ushort)IPAddress.HostToNetworkOrder((short)endPoint.Port);
|
|
}
|
|
sin.sin6_scope_id = (uint)endPoint.Address.ScopeId;
|
|
CollaborationHelperFunctions.ByteArrayToSin6Addr(endPoint.Address.GetAddressBytes(), ref sin);
|
|
pa.dwSize = 32;
|
|
pa.sin6 = sin;
|
|
return pa;
|
|
}
|
|
|
|
//
|
|
// Cleans up the registered handle and the wait event. Called under lock from events.
|
|
//
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
|
|
// <SatisfiesLinkDemand Name="SafeHandle.Dispose():System.Void" />
|
|
// <ReferencesCritical Name="Parameter safeEvent of type: SafeCollabEvent" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
[SecurityPermissionAttribute(SecurityAction.LinkDemand, UnmanagedCode = true)]
|
|
internal static void CleanEventVars(ref RegisteredWaitHandle waitHandle,
|
|
ref SafeCollabEvent safeEvent,
|
|
ref AutoResetEvent firedEvent)
|
|
{
|
|
if (waitHandle != null){
|
|
waitHandle.Unregister(null);
|
|
waitHandle = null;
|
|
}
|
|
|
|
if ((safeEvent != null) && (!safeEvent.IsInvalid)){
|
|
safeEvent.Dispose();
|
|
}
|
|
|
|
if (firedEvent != null){
|
|
firedEvent.Close();
|
|
firedEvent = null;
|
|
}
|
|
}
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
|
|
// <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" />
|
|
// <ReferencesCritical Name="Parameter safePresenceChangedEvent of type: SafeCollabEvent" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static void AddMyPresenceChanged(EventHandler<PresenceChangedEventArgs> callback,
|
|
ref EventHandler<PresenceChangedEventArgs> presenceChanged,
|
|
object lockPresenceChangedEvent,
|
|
ref RegisteredWaitHandle regPresenceChangedWaitHandle,
|
|
ref AutoResetEvent presenceChangedEvent,
|
|
ref SafeCollabEvent safePresenceChangedEvent,
|
|
WaitOrTimerCallback PresenceChangedCallback)
|
|
{
|
|
//
|
|
// Register a wait handle if one has not been registered already
|
|
//
|
|
lock (lockPresenceChangedEvent){
|
|
if (presenceChanged == null){
|
|
|
|
presenceChangedEvent = new AutoResetEvent(false);
|
|
|
|
//
|
|
// Register callback with a wait handle
|
|
//
|
|
|
|
regPresenceChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(presenceChangedEvent, //Event that triggers the callback
|
|
PresenceChangedCallback, //callback to be called
|
|
null, //state to be passed
|
|
-1, //Timeout - aplicable only for timers
|
|
false //call us everytime the event is set
|
|
);
|
|
PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
|
|
pcer.eventType = PeerCollabEventType.MyPresenceChanged;
|
|
pcer.pInstance = IntPtr.Zero;
|
|
|
|
|
|
//
|
|
// Register event with collab
|
|
//
|
|
|
|
int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
|
|
presenceChangedEvent.SafeWaitHandle,
|
|
1,
|
|
ref pcer,
|
|
out safePresenceChangedEvent);
|
|
if (errorCode != 0){
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_PresenceChangedRegFailed), errorCode);
|
|
}
|
|
}
|
|
presenceChanged += callback;
|
|
}
|
|
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddMyPresenceChanged() successful.");
|
|
}
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
|
|
// <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" />
|
|
// <ReferencesCritical Name="Parameter safeAppChangedEvent of type: SafeCollabEvent" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static void AddMyApplicationChanged(EventHandler<ApplicationChangedEventArgs> callback,
|
|
ref EventHandler<ApplicationChangedEventArgs> applicationChanged,
|
|
object lockAppChangedEvent,
|
|
ref RegisteredWaitHandle regAppChangedWaitHandle,
|
|
ref AutoResetEvent appChangedEvent,
|
|
ref SafeCollabEvent safeAppChangedEvent,
|
|
WaitOrTimerCallback ApplicationChangedCallback)
|
|
{
|
|
//
|
|
// Register a wait handle if one has not been registered already
|
|
//
|
|
lock (lockAppChangedEvent){
|
|
if (applicationChanged == null){
|
|
|
|
appChangedEvent = new AutoResetEvent(false);
|
|
|
|
//
|
|
// Register callback with a wait handle
|
|
//
|
|
|
|
regAppChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(appChangedEvent, //Event that triggers the callback
|
|
ApplicationChangedCallback, //callback to be called
|
|
null, //state to be passed
|
|
-1, //Timeout - aplicable only for timers
|
|
false //call us everytime the event is set
|
|
);
|
|
PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
|
|
|
|
pcer.eventType = PeerCollabEventType.MyApplicationChanged;
|
|
pcer.pInstance = IntPtr.Zero;
|
|
|
|
//
|
|
// Register event with collab
|
|
//
|
|
|
|
int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
|
|
appChangedEvent.SafeWaitHandle,
|
|
1,
|
|
ref pcer,
|
|
out safeAppChangedEvent);
|
|
if (errorCode != 0){
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ApplicationChangedRegFailed), errorCode);
|
|
}
|
|
}
|
|
applicationChanged += callback;
|
|
}
|
|
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddApplicationChanged() successful.");
|
|
}
|
|
|
|
// <SecurityKernel Critical="True" Ring="0">
|
|
// <SatisfiesLinkDemand Name="WaitHandle.get_SafeWaitHandle():Microsoft.Win32.SafeHandles.SafeWaitHandle" />
|
|
// <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" />
|
|
// <ReferencesCritical Name="Parameter safeObjChangedEvent of type: SafeCollabEvent" Ring="1" />
|
|
// <ReferencesCritical Name="Method: PeerToPeerException.CreateFromHr(System.String,System.Int32):System.Net.PeerToPeer.PeerToPeerException" Ring="1" />
|
|
// </SecurityKernel>
|
|
[System.Security.SecurityCritical]
|
|
internal static void AddMyObjectChanged(EventHandler<ObjectChangedEventArgs> callback,
|
|
ref EventHandler<ObjectChangedEventArgs> objectChanged,
|
|
object lockObjChangedEvent,
|
|
ref RegisteredWaitHandle regObjChangedWaitHandle,
|
|
ref AutoResetEvent objChangedEvent,
|
|
ref SafeCollabEvent safeObjChangedEvent,
|
|
WaitOrTimerCallback ObjectChangedCallback)
|
|
{
|
|
//
|
|
// Register a wait handle if one has not been registered already
|
|
//
|
|
lock (lockObjChangedEvent){
|
|
if (objectChanged == null){
|
|
|
|
objChangedEvent = new AutoResetEvent(false);
|
|
|
|
//
|
|
// Register callback with a wait handle
|
|
//
|
|
|
|
regObjChangedWaitHandle = ThreadPool.RegisterWaitForSingleObject(objChangedEvent, //Event that triggers the callback
|
|
ObjectChangedCallback, //callback to be called
|
|
null, //state to be passed
|
|
-1, //Timeout - aplicable only for timers
|
|
false //call us everytime the event is set
|
|
);
|
|
|
|
PEER_COLLAB_EVENT_REGISTRATION pcer = new PEER_COLLAB_EVENT_REGISTRATION();
|
|
pcer.eventType = PeerCollabEventType.MyObjectChanged;
|
|
pcer.pInstance = IntPtr.Zero;
|
|
|
|
|
|
//
|
|
// Register event with collab
|
|
//
|
|
|
|
int errorCode = UnsafeCollabNativeMethods.PeerCollabRegisterEvent(
|
|
objChangedEvent.SafeWaitHandle,
|
|
1,
|
|
ref pcer,
|
|
out safeObjChangedEvent);
|
|
if (errorCode != 0){
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Error, 0, "PeerCollabRegisterEvent returned with errorcode {0}", errorCode);
|
|
throw PeerToPeerException.CreateFromHr(SR.GetString(SR.Collab_ObjectChangedRegFailed), errorCode);
|
|
}
|
|
}
|
|
objectChanged += callback;
|
|
}
|
|
|
|
Logging.P2PTraceSource.TraceEvent(TraceEventType.Information, 0, "AddObjectChanged() successful.");
|
|
|
|
}
|
|
|
|
internal static void ThrowIfInvitationResponseInvalid(PeerInvitationResponse response)
|
|
{
|
|
// throw an exception if the response from the native API was PEER_INVITATION_RESPONSE_ERROR
|
|
if (response.PeerInvitationResponseType < PeerInvitationResponseType.Declined ||
|
|
response.PeerInvitationResponseType > PeerInvitationResponseType.Expired)
|
|
{
|
|
throw new PeerToPeerException(SR.GetString(SR.Collab_InviteFailed));
|
|
}
|
|
}
|
|
}
|
|
}
|