|
//------------------------------------------------------------------------------
// <copyright file="Logging.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System.Security.Permissions;
namespace System.Net.PeerToPeer
{
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.Security;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Threading;
using System.Net.Sockets;
using Microsoft.Win32;
using System.Diagnostics;
using System.IO;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct PEER_PNRP_CLOUD_INFO
{
internal IntPtr pwzCloudName;
internal UInt32 dwScope;
internal UInt32 dwScopeId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct PEER_PNRP_REGISTRATION_INFO
{
internal string pwszCloudName;
internal string pwszPublishingIdentity;
internal UInt32 cAddresses;
internal IntPtr ArrayOfSOCKADDRIN6Pointers;
internal ushort wport;
internal string pwszComment;
internal PEER_DATA payLoad;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct PEER_PNRP_ENDPOINT_INFO
{
internal IntPtr pwszPeerName;
internal UInt32 cAddresses;
internal IntPtr ArrayOfSOCKADDRIN6Pointers;
internal IntPtr pwszComment;
internal PEER_DATA payLoad;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct PEER_DATA
{
internal UInt32 cbPayload;
internal IntPtr pbPayload;
}
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class UnsafeP2PNativeMethods
{
internal const string P2P = "p2p.dll";
[DllImport(P2P, CharSet = CharSet.Unicode)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal extern static void PeerFreeData(IntPtr dataToFree);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerPnrpGetCloudInfo(out UInt32 pNumClouds, out SafePeerData pArrayOfClouds);
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerPnrpStartup(ushort versionRequired);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32
PeerCreatePeerName(string identity, string classfier, out SafePeerData peerName);
//[DllImport(P2P, CharSet = CharSet.Unicode)]
//internal extern static Int32 PeerCreatePeerName(string identity, string classfier, out SafePeerData peerName);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerIdentityGetDefault(out SafePeerData defaultIdentity);
/*
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerIdentityCreate(string classifier, string friendlyName, IntPtr hCryptoProv, out SafePeerData defaultIdentity);
*/
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerNameToPeerHostName(string peerName, out SafePeerData peerHostName);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
internal extern static Int32 PeerHostNameToPeerName(string peerHostName, out SafePeerData peerName);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpRegister(string pcwzPeerName,
ref PEER_PNRP_REGISTRATION_INFO registrationInfo,
out SafePeerNameUnregister handle);
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpUnregister(IntPtr handle);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpUpdateRegistration(SafePeerNameUnregister hRegistration,
ref PEER_PNRP_REGISTRATION_INFO registrationInfo);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpResolve(string pcwzPeerNAme,
string pcwzCloudName,
ref UInt32 pcEndPoints,
out SafePeerData pEndPoints);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpStartResolve(string pcwzPeerNAme,
string pcwzCloudName,
UInt32 cEndPoints,
SafeWaitHandle hEvent,
out SafePeerNameEndResolve safePeerNameEndResolve);
[SecurityCritical]
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpGetEndpoint(IntPtr Handle,
out SafePeerData pEndPoint);
[DllImport(P2P, CharSet = CharSet.Unicode)]
public extern static Int32 PeerPnrpEndResolve(IntPtr Handle);
private static object s_InternalSyncObject;
private static volatile bool s_Initialized;
private const int PNRP_VERSION = 2;
private static object InternalSyncObject {
get {
if (s_InternalSyncObject == null) {
object o = new object();
Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
}
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="PeerPnrpStartup(UInt16):Int32" />
// <SatisfiesLinkDemand Name="Marshal.GetExceptionForHR(System.Int32):System.Exception" />
// </SecurityKernel>
[System.Security.SecurityCritical]
internal static void PnrpStartup()
{
if (!s_Initialized) {
lock (InternalSyncObject) {
if (!s_Initialized) {
Int32 result = PeerPnrpStartup(PNRP_VERSION);
if (result != 0) {
throw new PeerToPeerException(SR.GetString(SR.Pnrp_StartupFailed), Marshal.GetExceptionForHR(result));
}
s_Initialized = true;
}
}
}
} //end of method PnrpStartup
}
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
// </SecurityKernel>
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal sealed class SafePeerData : SafeHandleZeroOrMinusOneIsInvalid
{
private SafePeerData() : base(true) { }
//private SafePeerData(bool ownsHandle) : base(ownsHandle) { }
internal string UnicodeString
{
get
{
return Marshal.PtrToStringUni(handle);
}
}
protected override bool ReleaseHandle()
{
UnsafeP2PNativeMethods.PeerFreeData(handle);
SetHandleAsInvalid(); //Mark it closed - This does not change the value of the handle it self
SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
return true;
}
}
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
// </SecurityKernel>
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal sealed class SafePeerNameUnregister : SafeHandleZeroOrMinusOneIsInvalid
{
internal SafePeerNameUnregister() : base(true) { }
//internal SafePeerNameUnregister(bool ownsHandle) : base(ownsHandle) { }
protected override bool ReleaseHandle()
{
UnsafeP2PNativeMethods.PeerPnrpUnregister(handle);
SetHandleAsInvalid(); //Mark it closed - This does not change the value of the handle it self
SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
return true;
}
}
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
// </SecurityKernel>
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal sealed class SafePeerNameEndResolve : SafeHandleZeroOrMinusOneIsInvalid
{
internal SafePeerNameEndResolve() : base(true) { }
//internal SafePeerNameEndResolve(bool ownsHandle) : base(ownsHandle) { }
protected override bool ReleaseHandle()
{
UnsafeP2PNativeMethods.PeerPnrpEndResolve(handle);
SetHandleAsInvalid(); //Mark it closed - This does not change the value of the handle it self
SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
return true;
}
}
/// <remarks>
/// Determines whether P2P is installed
/// Note static constructors are guaranteed to be
/// run in a thread safe manner. so no locks are necessary
/// </remarks>
internal static class PeerToPeerOSHelper
{
private const string OSInstallTypeRegKey = @"Software\Microsoft\Windows NT\CurrentVersion";
private const string OSInstallTypeRegKeyPath = @"HKEY_LOCAL_MACHINE\" + OSInstallTypeRegKey;
private const string OSInstallTypeRegName = "InstallationType";
private const string InstallTypeStringServerCore = "Server Core";
private static bool s_supportsP2P = false;
private static SafeLoadLibrary s_P2PLibrary = null;
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="UnsafeSystemNativeMethods.GetProcAddress(System.Net.SafeLoadLibrary,System.String):System.IntPtr" />
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
// <ReferencesCritical Name="Field: s_P2PLibrary" Ring="1" />
// <ReferencesCritical Name="Method: SafeLoadLibrary.LoadLibraryEx(System.String):System.Net.SafeLoadLibrary" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
static PeerToPeerOSHelper() {
if (IsSupportedOS()) {
// if OS is supported, but p2p.dll is not available, P2P is not supported (original behavior)
string dllFileName = Path.Combine(Environment.SystemDirectory, UnsafeP2PNativeMethods.P2P);
s_P2PLibrary = SafeLoadLibrary.LoadLibraryEx(dllFileName);
if (!s_P2PLibrary.IsInvalid) {
IntPtr Address = UnsafeSystemNativeMethods.GetProcAddress(s_P2PLibrary, "PeerCreatePeerName");
if (Address != IntPtr.Zero) {
s_supportsP2P = true;
}
}
}
//else --> the SafeLoadLibrary would have already been marked
// closed by the LoadLibraryEx call above.
}
[SecurityCritical]
private static bool IsSupportedOS()
{
// extend this method when adding further OS/install type restrictions
// P2P is not supported on Server Core installation type
if (IsServerCore()) {
return false;
}
return true;
}
[SecurityCritical]
[RegistryPermission(SecurityAction.Assert, Read = OSInstallTypeRegKeyPath)]
private static bool IsServerCore()
{
// This code does the same as System.Net.ComNetOS.GetWindowsInstallType(). Since ComNetOS is internal and
// we don't want to add InternalsVisibleToAttribute to System.dll, we have to duplicate the code.
try {
using (RegistryKey installTypeKey = Registry.LocalMachine.OpenSubKey(OSInstallTypeRegKey)) {
string installType = installTypeKey.GetValue(OSInstallTypeRegName) as string;
if (string.IsNullOrEmpty(installType)) {
Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
SR.GetString(SR.P2P_empty_osinstalltype, OSInstallTypeRegKey + "\\" + OSInstallTypeRegName));
}
else {
if (String.Compare(installType, InstallTypeStringServerCore, StringComparison.OrdinalIgnoreCase) == 0) {
return true;
}
}
}
}
catch (UnauthorizedAccessException e) {
Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
SR.GetString(SR.P2P_cant_determine_osinstalltype, OSInstallTypeRegKey, e.Message));
}
catch (SecurityException e) {
Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
SR.GetString(SR.P2P_cant_determine_osinstalltype, OSInstallTypeRegKey, e.Message));
}
return false;
}
internal static bool SupportsP2P {
get {
return s_supportsP2P;
}
}
internal static IntPtr P2PModuleHandle
{
// <SecurityKernel Critical="True" Ring="0">
// <SatisfiesLinkDemand Name="SafeHandle.get_IsClosed():System.Boolean" />
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
// <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
// <ReferencesCritical Name="Field: s_P2PLibrary" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
[SecurityPermissionAttribute(SecurityAction.LinkDemand, UnmanagedCode=true)]
get
{
if (!s_P2PLibrary.IsClosed && !s_P2PLibrary.IsInvalid)
return s_P2PLibrary.DangerousGetHandle();
return IntPtr.Zero;
}
}
}
}
|