Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
2010-05-29 Robert Jordan <robertj@gmx.net>
* IpcChannelHelper.cs (copy): Take into account that the remoting
stack is internally using MemoryStreams all over the place.
Fixes bug #609381 as a side effect.
* IpcChannel.cs (.ctor): Create an IpcClientChannel as well.
2005-11-05 Robert Jordan <robertj@gmx.net>
* IpcClientChannel.cs, IpcServerChannel.cs: Added missing ctors.
2005-11-04 Robert Jordan <robertj@gmx.net>
* IpcChannelHelper.cs: Removed the colon from the invalid pipe name
chars, because it is a valid char on NT systems and some .NET IPC
channel samples contain a colon in their port names.
2005-10-16 Robert Jordan <robertj@gmx.net>
* Imported

View File

@@ -0,0 +1,144 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.IpcChannel.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
internal class IpcChannel : IChannelSender, IChannelReceiver, IChannel
{
readonly IpcClientChannel clientChannel;
readonly IpcServerChannel serverChannel;
/// <summary>
/// Creates a client channel.
/// </summary>
public IpcChannel()
{
clientChannel = new IpcClientChannel();
}
/// <summary>
/// Creates a server channel.
/// </summary>
/// <param name="portName">The port name.</param>
public IpcChannel(string portName)
: this()
{
serverChannel = new IpcServerChannel(portName);
}
/// <summary>
/// Creates both server and client channels.
/// </summary>
/// <param name="properties">The channel properties.</param>
/// <param name="clientProvider">The client sink provider. It may be <c>null</c>.</param>
/// <param name="serverProvider">The server sink provider. It may be <c>null</c>.</param>
public IpcChannel(IDictionary properties,
IClientChannelSinkProvider clientProvider,
IServerChannelSinkProvider serverProvider
)
{
clientChannel = new IpcClientChannel(properties, clientProvider);
serverChannel = new IpcServerChannel(properties, serverProvider);
}
#region IChannelSender Members
public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
{
return clientChannel.CreateMessageSink(url, remoteChannelData, out objectURI);
}
#endregion
#region IChannel Members
public string ChannelName
{
get
{
return serverChannel != null
? serverChannel.ChannelName
: clientChannel.ChannelName;
}
}
public int ChannelPriority
{
get
{
return serverChannel != null
? serverChannel.ChannelPriority
: clientChannel.ChannelPriority;
}
}
public string Parse(string url, out string objectURI)
{
return IpcChannelHelper.Parse(url, out objectURI);
}
#endregion
#region IChannelReceiver Members
public void StartListening(object data)
{
serverChannel.StartListening(data);
}
public object ChannelData
{
get
{
return serverChannel != null ? serverChannel.ChannelData : null;
}
}
public void StopListening(object data)
{
serverChannel.StopListening(data);
}
public string[] GetUrlsForUri(string objectURI)
{
return serverChannel.GetUrlsForUri(objectURI);
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,145 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.IpcChannelHelper.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Formatters.Binary;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Provides helper services to the IpcChannel implementation.
/// </summary>
internal sealed class IpcChannelHelper
{
public const string Scheme = "ipc";
public const string SchemeStart = "ipc://";
IpcChannelHelper()
{
}
static readonly char[] InvalidPipeNameChars =
new char[] {'\\', '/'};
/// <summary>
/// Validates a pipe name.
/// </summary>
/// <param name="pipeName">The pipe name.</param>
/// <returns></returns>
public static bool IsValidPipeName(string pipeName)
{
if (pipeName == null || pipeName.Trim() == "")
return false;
if (pipeName.IndexOfAny(Path.InvalidPathChars) >= 0)
return false;
if (pipeName.IndexOfAny(InvalidPipeNameChars) >= 0)
return false;
return true;
}
/// <summary>
/// Parses an url against IpcChannel's rules.
/// </summary>
/// <param name="url">The url.</param>
/// <param name="pipeName">The pipe name.</param>
/// <param name="objectUri">The uri of the object.</param>
/// <returns>All but the object uri.</returns>
public static string Parse(string url, out string pipeName, out string objectUri)
{
if (url.StartsWith(SchemeStart))
{
int i = url.IndexOf('/', SchemeStart.Length);
if (i >= 0)
{
pipeName = url.Substring(SchemeStart.Length, i - SchemeStart.Length);
objectUri = url.Substring(i);
return SchemeStart + pipeName;
}
else
{
pipeName = url.Substring(SchemeStart.Length);
objectUri = null;
return SchemeStart + pipeName;
}
}
pipeName = null;
objectUri = null;
return null;
}
/// <summary>
/// Parses an url against IpcChannel's rules.
/// </summary>
/// <param name="url">The url.</param>
/// <param name="objectUri">The uri of the object.</param>
/// <returns>All but the object uri.</returns>
public static string Parse(string url, out string objectUri)
{
string pipeName;
return Parse(url, out pipeName, out objectUri);
}
/// <summary>
/// Copies a stream.
/// </summary>
/// <param name="input"></param>
/// <param name="output"></param>
public static void Copy(Stream input, Stream output)
{
MemoryStream ms = input as MemoryStream;
if (ms != null)
{
ms.WriteTo (output);
return;
}
// TODO: find out the optimal chunk size.
const int size = 1024 * 1024;
byte[] buffer = new byte[size];
int count;
while ((count = input.Read(buffer, 0, size)) > 0)
{
output.Write(buffer, 0, count);
}
}
}
}
#endif

View File

@@ -0,0 +1,283 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.IpcClientChannel.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
internal class IpcClientChannel : IChannelSender, IChannel
{
readonly string channelName = IpcChannelHelper.Scheme;
readonly int channelPriority = 1;
readonly IClientChannelSinkProvider clientProvider;
/// <summary>
/// Creates a default client channel.
/// </summary>
public IpcClientChannel()
: this ((IDictionary)null, null)
{
}
/// <summary>
/// Creates a default client channel.
/// </summary>
/// <param name="name">The channel name.</param>
/// <param name="sinkProvider">The provider</param>
public IpcClientChannel(string name, IClientChannelSinkProvider provider)
: this (IpcServerChannel.BuildDefaultProperties (name), provider)
{
}
/// <summary>
/// Creates a client channel.
/// </summary>
/// <param name="properties">The properties.</param>
/// <param name="sinkProvider">The provider</param>
public IpcClientChannel(IDictionary properties, IClientChannelSinkProvider provider)
{
if (properties != null)
{
foreach (DictionaryEntry e in properties)
{
switch ((string)e.Key)
{
case "name":
channelName = (string)e.Value;
break;
case "priority":
channelPriority = Convert.ToInt32(e.Value);
break;
}
}
}
if (provider == null)
{
clientProvider = new BinaryClientFormatterSinkProvider();
clientProvider.Next = new IpcClientChannelSinkProvider();
}
else
{
// add us to the sink chain.
clientProvider = provider;
IClientChannelSinkProvider p;
for (p = clientProvider; p.Next != null; p = p.Next) {}
p.Next = new IpcClientChannelSinkProvider();
}
}
#region IChannelSender Members
public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
{
objectURI = null;
string channelUri = null;
if (url != null)
{
channelUri = Parse(url, out objectURI);
}
if (channelUri == null)
{
// get url from the channel data
IChannelDataStore ds = remoteChannelData as IChannelDataStore;
if (ds != null)
{
channelUri = Parse(ds.ChannelUris[0], out objectURI);
if (channelUri != null)
url = ds.ChannelUris[0];
}
}
if (channelUri != null)
{
return (IMessageSink) clientProvider.CreateSink(this, url, remoteChannelData);
}
else
{
return null;
}
}
#endregion
#region IChannel Members
public string ChannelName
{
get
{
return channelName;
}
}
public int ChannelPriority
{
get
{
return channelPriority;
}
}
public string Parse(string url, out string objectURI)
{
return IpcChannelHelper.Parse(url, out objectURI);
}
#endregion
}
internal class IpcClientChannelSinkProvider : IClientChannelSinkProvider
{
#region IClientChannelSinkProvider Members
public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData)
{
return new IpcClientChannelSink(url);
}
public IClientChannelSinkProvider Next
{
get
{
return null;
}
set
{
throw new NotSupportedException();
}
}
#endregion
}
internal class IpcClientChannelSink : IClientChannelSink
{
readonly string pipeName;
public IpcClientChannelSink(string url)
{
string unused;
IpcChannelHelper.Parse(url, out pipeName, out unused);
}
#region IClientChannelSink Members
delegate void AsyncResponse(IClientChannelSinkStack sinkStack, IpcTransport transport);
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream)
{
headers[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
// connect
NamedPipeClient client = new NamedPipeClient(pipeName);
NamedPipeSocket socket = client.Connect();
IpcTransport t = new IpcTransport(socket);
t.Write(headers, stream);
// schedule an async call
if (!RemotingServices.IsOneWay(((IMethodCallMessage)msg).MethodBase))
{
new AsyncResponse(AsyncHandler).BeginInvoke(sinkStack, t, null, null);
}
}
void AsyncHandler(IClientChannelSinkStack sinkStack, IpcTransport transport)
{
try
{
// get the response headers and the response stream from the server
ITransportHeaders responseHeaders;
Stream responseStream;
transport.Read(out responseHeaders, out responseStream);
transport.Close();
sinkStack.AsyncProcessResponse(responseHeaders, responseStream);
}
catch (Exception ex)
{
sinkStack.DispatchException(ex);
}
}
public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream)
{
responseHeaders = null;
responseStream = null;
requestHeaders[CommonTransportKeys.RequestUri] = ((IMethodCallMessage)msg).Uri;
// connect
NamedPipeClient client = new NamedPipeClient(pipeName);
NamedPipeSocket socket = client.Connect();
IpcTransport t = new IpcTransport(socket);
t.Write(requestHeaders, requestStream);
t.Read(out responseHeaders, out responseStream);
t.Close();
}
public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
{
return null;
}
public IClientChannelSink NextChannelSink
{
get { return null; }
}
#endregion
#region IChannelSinkBase Members
public IDictionary Properties
{
get { return null; }
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,390 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.IpcServerChannel.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
internal class IpcServerChannel : IChannelReceiver, IChannel
{
readonly string portName;
readonly string channelName = IpcChannelHelper.Scheme;
readonly int channelPriority = 1;
readonly IServerChannelSinkProvider serverProvider;
readonly IpcServerChannelSink sink;
readonly ChannelDataStore dataStore;
Thread worker;
/// <summary>
/// Builds the default channel properties
/// </summary>
/// <param name="portName">The pipe name.</param>
/// <returns></returns>
internal static IDictionary BuildDefaultProperties(string portName)
{
Hashtable h = new Hashtable();
h.Add("portName", portName);
return h;
}
/// <summary>
/// Builds the default channel properties
/// </summary>
/// <param name="portName">The pipe name.</param>
/// <returns></returns>
internal static IDictionary BuildDefaultProperties(string name, string portName)
{
Hashtable h = new Hashtable();
h.Add("name", name);
h.Add("portName", portName);
return h;
}
/// <summary>
/// Creates a server channel
/// </summary>
/// <param name="portName">The port name.</param>
public IpcServerChannel(string portName)
: this(BuildDefaultProperties(portName), null)
{
}
/// <summary>
/// Creates a server channel
/// </summary>
/// <param name="mame">The channel name.</param>
/// <param name="portName">The port name.</param>
public IpcServerChannel(string name, string portName)
: this(BuildDefaultProperties(name, portName), null)
{
}
/// <summary>
/// Creates a server channel
/// </summary>
/// <param name="mame">The channel name.</param>
/// <param name="portName">The port name.</param>
/// <param name="provider">The sink provider.</param>
public IpcServerChannel(string name, string portName,
IServerChannelSinkProvider provider)
: this(BuildDefaultProperties(name, portName), provider)
{
}
/// <summary>
/// Creates a server channel.
/// </summary>
/// <param name="properties">The channel properties.</param>
/// <param name="provider">The sink provider.</param>
public IpcServerChannel(IDictionary properties, IServerChannelSinkProvider provider)
{
bool impersonate = false;
if (properties != null)
{
foreach (DictionaryEntry e in properties)
{
switch ((string)e.Key)
{
case "name":
channelName = (string)e.Value;
break;
case "priority":
channelPriority = Convert.ToInt32(e.Value);
break;
case "portName":
portName = (string)e.Value;
if (!IpcChannelHelper.IsValidPipeName(portName))
throw new ArgumentException("Invalid pipe name.", "portName");
break;
case "impersonate":
impersonate = Boolean.Parse((string)e.Value);
break;
}
}
}
if (portName == null)
{
portName = Guid.NewGuid().ToString("N");
}
serverProvider = provider;
if (serverProvider == null)
{
serverProvider = new BinaryServerFormatterSinkProvider();
}
dataStore = new ChannelDataStore(
new string[] {IpcChannelHelper.SchemeStart + portName}
);
PopulateChannelData(dataStore, serverProvider);
sink = new IpcServerChannelSink(
ChannelServices.CreateServerChannelSinkChain(serverProvider, this),
portName,
impersonate
);
StartListening(null);
}
void PopulateChannelData( ChannelDataStore channelData,
IServerChannelSinkProvider provider)
{
while (provider != null)
{
provider.GetChannelData(channelData);
provider = provider.Next;
}
}
#region IChannelReceiver Members
public void StartListening(object data)
{
if (worker == null)
{
worker = new Thread(new ThreadStart(sink.Listen));
worker.IsBackground = true;
worker.Start();
}
}
public object ChannelData
{
get
{
return dataStore;
}
}
public void StopListening(object data)
{
if (worker != null)
{
worker.Abort();
worker = null;
}
}
public string[] GetUrlsForUri(string objectURI)
{
if (!objectURI.StartsWith("/")) objectURI = "/" + objectURI;
string[] urls = new string[1];
urls[0] = IpcChannelHelper.SchemeStart + portName + objectURI;
return urls;
}
#endregion
#region IChannel Members
public string ChannelName
{
get
{
return channelName;
}
}
public int ChannelPriority
{
get
{
return channelPriority;
}
}
public string Parse(string url, out string objectURI)
{
return IpcChannelHelper.Parse(url, out objectURI);
}
#endregion
}
internal class IpcServerChannelSink : IServerChannelSink
{
IServerChannelSink nextSink;
string portName;
bool impersonate;
public IpcServerChannelSink(IServerChannelSink nextSink, string portName, bool impersonate)
{
this.nextSink = nextSink;
this.portName = portName;
this.impersonate = impersonate;
}
#region IServerChannelSink Members
public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers)
{
return null;
}
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
{
throw new NotSupportedException();
}
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream)
{
}
public IServerChannelSink NextChannelSink
{
get
{
return nextSink;
}
}
#endregion
#region IChannelSinkBase Members
public IDictionary Properties
{
get
{
return null;
}
}
/// <summary>
/// Listens for incoming requests.
/// </summary>
internal void Listen()
{
while (true)
{
try
{
NamedPipeListener listener = new NamedPipeListener(portName);
NamedPipeSocket socket = listener.Accept();
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), socket);
}
catch (NamedPipeException)
{
}
}
}
void ProcessClient(object state)
{
try
{
NamedPipeSocket socket = (NamedPipeSocket) state;
ITransportHeaders requestHeaders;
Stream requestStream;
IpcTransport t = new IpcTransport(socket);
t.Read(out requestHeaders, out requestStream);
// parse the RequestUri
string objectUri;
string uri = (string) requestHeaders[CommonTransportKeys.RequestUri];
IpcChannelHelper.Parse(uri, out objectUri);
if (objectUri == null) objectUri = uri;
requestHeaders[CommonTransportKeys.RequestUri] = objectUri;
ServerChannelSinkStack stack = new ServerChannelSinkStack();
stack.Push(this, null);
IMessage responseMsg;
ITransportHeaders responseHeaders;
Stream responseStream;
requestHeaders["__CustomErrorsEnabled"] = false;
if (impersonate)
{
// TODO: Impersonate might throw exceptions. What to do with them?
socket.Impersonate();
}
ServerProcessing op = nextSink.ProcessMessage(
stack,
null,
requestHeaders,
requestStream,
out responseMsg,
out responseHeaders,
out responseStream
);
if (impersonate)
{
NamedPipeSocket.RevertToSelf();
}
switch (op)
{
case ServerProcessing.Complete:
stack.Pop(this);
// send the response headers and the response data to the client
t.Write(responseHeaders, responseStream);
break;
case ServerProcessing.Async:
stack.StoreAndDispatch(nextSink, null);
break;
case ServerProcessing.OneWay:
break;
}
}
catch (Exception)
{
// Console.WriteLine(ex);
}
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,139 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.IpcTransport.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Formatters.Binary;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// IPC transport helper
/// </summary>
internal class IpcTransport
{
readonly NamedPipeSocket socket;
readonly BinaryFormatter formatter = new BinaryFormatter();
/// <summary>
/// Creates a new object.
/// </summary>
/// <param name="socket">The named pipe.</param>
public IpcTransport(NamedPipeSocket socket)
{
this.socket = socket;
}
/// <summary>
/// Writes a request.
/// </summary>
/// <param name="header"></param>
/// <param name="requestStream"></param>
public void Write(ITransportHeaders header, Stream requestStream)
{
Stream bs = socket.GetStream();
MemoryStream m = new MemoryStream();
formatter.Serialize(m, header);
m.Position = 0;
byte[] bytes = BitConverter.GetBytes((int)m.Length);
bs.Write(bytes, 0, bytes.Length);
m.WriteTo(bs);
try
{
bytes = BitConverter.GetBytes((int)requestStream.Length);
bs.Write(bytes, 0, bytes.Length);
IpcChannelHelper.Copy(requestStream, bs);
}
catch
{
bs.Write(bytes, 0, bytes.Length);
}
bs.Flush();
}
/// <summary>
/// Reads a response.
/// </summary>
/// <param name="headers"></param>
/// <param name="responseStream"></param>
public void Read(out ITransportHeaders headers, out Stream responseStream)
{
byte[] bytes;
long length;
bytes = BitConverter.GetBytes(int.MaxValue);
socket.Receive(bytes, 0, bytes.Length);
length = BitConverter.ToInt32(bytes, 0);
if (length != int.MaxValue && length > 0)
{
bytes = new byte[length];
socket.Receive(bytes, 0, (int)length);
MemoryStream m = new MemoryStream(bytes);
headers = (ITransportHeaders) formatter.Deserialize(m);
}
else
{
headers = new TransportHeaders();
}
bytes = BitConverter.GetBytes(int.MaxValue);
socket.Receive(bytes, 0, bytes.Length);
length = BitConverter.ToInt32(bytes, 0);
if (length != int.MaxValue && length > 0)
{
bytes = new byte[length];
socket.Receive(bytes, 0, (int)length);
responseStream = new MemoryStream(bytes);
}
else
{
responseStream = new MemoryStream(new byte[0]);
}
}
/// <summary>
/// Closes the unterlying named pipe socket.
/// </summary>
public void Close()
{
socket.Close();
}
}
}
#endif

View File

@@ -0,0 +1,115 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeClient.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Runtime.InteropServices;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Provides client connections for local Named Pipes.
/// </summary>
internal class NamedPipeClient
{
readonly string pipeName;
public string Name
{
get { return pipeName; }
}
/// <summary>
/// Creates a new instance with the local Named Pipe name specified as an unique ID.
/// </summary>
/// <param name="uid">The Guid.</param>
public NamedPipeClient(Guid uid)
: this(uid.ToString("N"))
{
}
/// <summary>
/// Creates a new instance for the specified pipe name.
/// </summary>
/// <param name="pipeName">The pipe name omiting the leading <c>\\.\pipe\</c></param>
public NamedPipeClient(string pipeName)
{
this.pipeName = NamedPipeHelper.FormatPipeName(pipeName);
}
/// <summary>
/// Connects to a local Named Pipe server.
/// </summary>
/// <returns>The NamedPipeSocket</returns>
public NamedPipeSocket Connect()
{
return Connect(2000);
}
/// <summary>
/// Connects to a local Named Pipe server.
/// </summary>
/// <param name="timeout">Timeout in millisecons to wait for the connection.</param>
/// <returns></returns>
public NamedPipeSocket Connect(int timeout)
{
while (true)
{
IntPtr hPipe = NamedPipeHelper.CreateFile(
pipeName,
NamedPipeHelper.GENERIC_READ |
NamedPipeHelper.GENERIC_WRITE,
0,
IntPtr.Zero,
NamedPipeHelper.OPEN_EXISTING,
0,
IntPtr.Zero
);
if (hPipe.ToInt32() == NamedPipeHelper.INVALID_HANDLE_VALUE)
{
int lastError = Marshal.GetLastWin32Error();
if (lastError != NamedPipeHelper.ERROR_PIPE_BUSY)
throw new NamedPipeException(lastError);
if (!NamedPipeHelper.WaitNamedPipe(pipeName, timeout))
{
throw new NamedPipeException();
}
}
else
{
return new NamedPipeSocket(hPipe);
}
}
}
}
}
#endif

View File

@@ -0,0 +1,66 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeException.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// The exception that is thrown for a Win32 error code.
/// </summary>
[Serializable]
internal class NamedPipeException : Win32Exception
{
public NamedPipeException()
: base()
{
}
public NamedPipeException(int error)
: base(error)
{
}
public NamedPipeException(int error, string message)
: base(error, message)
{
}
protected NamedPipeException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
#endif

View File

@@ -0,0 +1,229 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeHelper.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Named Pipe P/Invoke declarations.
/// </summary>
internal sealed class NamedPipeHelper
{
NamedPipeHelper()
{
}
/// <summary>
/// Returns a properly formatted local pipe name.
/// </summary>
/// <param name="pipeName"></param>
/// <returns></returns>
public static string FormatPipeName(string pipeName)
{
return String.Format(@"\\.\pipe\{0}", pipeName);
}
#region P/Invoke
// Named pipe acces flags
public const uint PIPE_ACCESS_INBOUND = 1;
public const uint PIPE_ACCESS_OUTBOUND = 2;
public const uint PIPE_ACCESS_DUPLEX = 3;
// Named pipe wait states
public const uint PIPE_WAIT = 0;
public const uint PIPE_NOWAIT = 1;
// Named pipe message types
public const uint PIPE_TYPE_BYTE = 0;
public const uint PIPE_TYPE_MESSAGE = 4;
// Named pipe message read modes
public const uint PIPE_READMODE_BYTE = 0;
public const uint PIPE_READMODE_MESSAGE = 2;
// Named pipe endpoints
public const uint PIPE_CLIENT_END = 0;
public const uint PIPE_SERVER_END = 1;
// Named pipe misc flags
public const uint PIPE_UNLIMITED_INSTANCES = 255;
// Named pipe wait flags
public const uint NMPWAIT_USE_DEFAULT_WAIT = 0;
public const uint NMPWAIT_NOWAIT = 1;
public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;
// Create flags
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
public const uint OPEN_ALWAYS = 4;
public const uint TRUNCATE_EXISTING = 5;
// Access flags
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint GENERIC_EXECUTE = 0x20000000;
public const uint GENERIC_ALL = 0x10000000;
// Error results
public const int ERROR_FILE_NOT_FOUND = 2;
public const int ERROR_PIPE_BUSY = 231;
public const int ERROR_NO_DATA = 232;
public const int ERROR_PIPE_NOT_CONNECTED = 233;
public const int ERROR_PIPE_CONNECTED = 535;
public const int ERROR_PIPE_LISTENING = 536;
public const int INVALID_HANDLE_VALUE = -1;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(
string lpName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr pipeSecurityDescriptor
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ConnectNamedPipe(
IntPtr hPipe,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
String lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr attr,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(
IntPtr hHandle,
IntPtr lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFile(
IntPtr hHandle,
IntPtr lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetNamedPipeHandleState(
IntPtr hPipe,
out int lpState,
out int lpCurInstances,
out int lpMaxCollectionCount,
out int lpCollectDataTimeout,
StringBuilder lpUserName,
int nMaxUserNameSize
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetNamedPipeHandleState(
IntPtr hPipe,
ref uint lpMode,
ref uint lpMaxCollectionCount,
ref uint lpCollectDataTimeout
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetNamedPipeInfo(
IntPtr hPipe,
out int lpFlags,
out int lpOutBufferSize,
out int lpInBufferSize,
out int lpMaxInstances
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool PeekNamedPipe(
IntPtr hPipe,
IntPtr lpBuffer,
uint nBufferSize,
out uint lpBytesRead,
out uint lpTotalBytesAvail,
out uint lpBytesLeftThisMessage
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WaitNamedPipe(
string name,
int timeout
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DisconnectNamedPipe(
IntPtr hPipe
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FlushFileBuffers(
IntPtr hFile
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hHandle
);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool ImpersonateNamedPipeClient(
IntPtr hPipe
);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool RevertToSelf();
#endregion
}
}
#endif

View File

@@ -0,0 +1,113 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeListener.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.Runtime.InteropServices;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Listens for connections from local local Named Pipe clients.
/// </summary>
internal class NamedPipeListener
{
const uint DefaultBufferSize = 4096;
readonly string pipeName;
public string Name
{
get { return pipeName; }
}
/// <summary>
/// Creates a new listener with the local local Named Pipe name obtained form the specified UID.
/// </summary>
/// <param name="uid">The UID.</param>
public NamedPipeListener(Guid uid)
: this(uid.ToString("N"))
{
}
/// <summary>
/// Creates a new listener with the specified name.
/// </summary>
/// <param name="pipeName">The pipe name omiting the leading <c>\\.\pipe\</c></param>
public NamedPipeListener(string pipeName)
{
this.pipeName = NamedPipeHelper.FormatPipeName(pipeName);
}
/// <summary>
/// Accepts a pending connection request
/// </summary>
/// <remarks>
/// Accept is a blocking method that returns a NamedPipeSocket you can use to send and receive data.
/// </remarks>
/// <returns>The NamedPipeSocket.</returns>
public NamedPipeSocket Accept()
{
IntPtr hPipe = NamedPipeHelper.CreateNamedPipe(
pipeName,
NamedPipeHelper.PIPE_ACCESS_DUPLEX,
NamedPipeHelper.PIPE_TYPE_MESSAGE
| NamedPipeHelper.PIPE_READMODE_MESSAGE
| NamedPipeHelper.PIPE_WAIT,
NamedPipeHelper.PIPE_UNLIMITED_INSTANCES,
DefaultBufferSize,
DefaultBufferSize,
NamedPipeHelper.NMPWAIT_USE_DEFAULT_WAIT,
IntPtr.Zero
);
if (hPipe.ToInt32() == NamedPipeHelper.INVALID_HANDLE_VALUE)
{
throw new NamedPipeException();
}
bool canConnect = NamedPipeHelper.ConnectNamedPipe(hPipe, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
if (!canConnect && lastError == NamedPipeHelper.ERROR_PIPE_CONNECTED)
canConnect = true;
if (canConnect)
{
return new NamedPipeSocket(hPipe);
}
else
{
NamedPipeHelper.CloseHandle(hPipe);
throw new NamedPipeException(lastError);
}
}
}
}
#endif

View File

@@ -0,0 +1,369 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeSocket.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Implements a local Named Pipe socket.
/// </summary>
internal class NamedPipeSocket : IDisposable
{
IntPtr hPipe;
/// <summary>
/// Creates a new socket instance form the specified local Named Pipe handle.
/// </summary>
/// <param name="hPipe">The handle.</param>
internal NamedPipeSocket(IntPtr hPipe)
{
this.hPipe = hPipe;
this.info = new NamedPipeSocketInfo(hPipe);
}
~NamedPipeSocket()
{
((IDisposable)this).Dispose();
}
/// <summary>
/// Gets the NamedPipeSocketInfo of this instance.
/// </summary>
/// <returns></returns>
public NamedPipeSocketInfo Info
{
get
{
return info;
}
}
NamedPipeSocketInfo info;
/// <summary>
/// Closes the socket.
/// </summary>
public void Close()
{
((IDisposable)this).Dispose();
}
/// <summary>
/// Disposes the object.
/// </summary>
void IDisposable.Dispose()
{
if (hPipe != IntPtr.Zero)
{
try
{
// disconnect the pipe
if (Info.IsServer)
{
NamedPipeHelper.FlushFileBuffers(hPipe);
NamedPipeHelper.DisconnectNamedPipe(hPipe);
}
}
catch (NamedPipeException)
{
}
NamedPipeHelper.CloseHandle(hPipe);
hPipe = IntPtr.Zero;
GC.SuppressFinalize(this);
}
}
/// <summary>
/// Returns the stream used to send and receive data.
/// </summary>
/// <returns></returns>
public Stream GetStream()
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
return stream == null
? stream = new NamedPipeStream(this, false)
: stream;
}
Stream stream;
/// <summary>
/// Returns the stream used to send and receive data. The stream disposes
/// the socket on close.
/// </summary>
/// <returns></returns>
public Stream GetClosingStream()
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
return new NamedPipeStream(this, true);
}
/// <summary>
/// Flushes the socket.
/// </summary>
public void Flush()
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
NamedPipeHelper.FlushFileBuffers(hPipe);
}
/// <summary>
/// Receives the specified number of bytes from a socket into
/// the specified offset position of the receive buffer.
/// </summary>
/// <param name="buffer">An array of type Byte that is the storage
/// location for received data.</param>
/// <param name="offset">The location in buffer to store the received data.</param>
/// <param name="count">The number of bytes to receive.</param>
/// <returns>The number of bytes received.</returns>
public int Receive(byte[] buffer, int offset, int count)
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
if (buffer == null)
throw new ArgumentNullException("buffer");
if (offset < 0 || count < 0)
throw new ArgumentOutOfRangeException("offset and/or count");
if (buffer.Length - offset < count)
throw new ArgumentException();
uint read = 0;
GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
bool res = NamedPipeHelper.ReadFile(
hPipe,
Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
(uint) count,
out read,
IntPtr.Zero
);
if (!res && read == 0) throw new NamedPipeException();
return (int) read;
}
finally
{
gch.Free();
}
}
delegate int ReceiveMethod(byte[] buffer, int offset, int count);
public IAsyncResult BeginReceive(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return new ReceiveMethod(Receive).BeginInvoke(buffer, offset, count, callback, state);
}
public int EndReceive(IAsyncResult asyncResult)
{
AsyncResult ar = asyncResult as AsyncResult;
return ((ReceiveMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
}
/// <summary>
/// Sends the specified number of bytes of data to a connected socket,
/// starting at the specified offset.
/// </summary>
/// <param name="buffer">An array of type Byte that contains the data to be sent.</param>
/// <param name="offset">The position in the data buffer at which to begin sending data. </param>
/// <param name="count">The number of bytes to send.</param>
/// <returns>The number of bytes sent.</returns>
public int Send(byte[] buffer, int offset, int count)
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
if (buffer == null)
throw new ArgumentNullException("buffer");
if (offset < 0 || count < 0)
throw new ArgumentOutOfRangeException("offset and/or count");
if (buffer.Length - offset < count)
throw new ArgumentException();
uint written = 0;
GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
bool res = NamedPipeHelper.WriteFile(
hPipe,
Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
(uint) count,
out written,
IntPtr.Zero
);
if (!res) throw new NamedPipeException();
return (int) written;
}
finally
{
gch.Free();
}
}
delegate int SendMethod(byte[] buffer, int offset, int count);
public IAsyncResult BeginSend(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return new SendMethod(Send).BeginInvoke(buffer, offset, count, callback, state);
}
public int EndSend(IAsyncResult asyncResult)
{
AsyncResult ar = asyncResult as AsyncResult;
return ((SendMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
}
/// <summary>
/// Returns the current NamedPipeSocketState of this instance.
/// </summary>
/// <returns></returns>
public NamedPipeSocketState GetSocketState()
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
return new NamedPipeSocketState(hPipe);
}
/// <summary>
/// Impersonates the client.
/// </summary>
public void Impersonate()
{
if (hPipe == IntPtr.Zero)
throw new ObjectDisposedException(GetType().FullName);
if (Info.IsServer)
if (!NamedPipeHelper.ImpersonateNamedPipeClient(hPipe))
throw new NamedPipeException();
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
public static bool RevertToSelf()
{
return NamedPipeHelper.RevertToSelf();
}
}
/// <summary>
/// Represents local Named Pipe informations.
/// </summary>
internal class NamedPipeSocketInfo
{
public readonly int Flags;
public readonly int OutBufferSize;
public readonly int InBufferSize;
public readonly int MaxInstances;
public bool IsServer
{
get
{
return (Flags & NamedPipeHelper.PIPE_SERVER_END) != 0;
}
}
internal NamedPipeSocketInfo(IntPtr hPipe)
{
bool res = NamedPipeHelper.GetNamedPipeInfo(
hPipe,
out Flags,
out OutBufferSize,
out InBufferSize,
out MaxInstances
);
if (!res)
{
throw new NamedPipeException();
}
}
}
/// <summary>
/// Represents local Named Pipe state informations.
/// </summary>
internal class NamedPipeSocketState
{
public readonly int State;
public readonly int CurrentInstances;
public readonly int MaxCollectionCount;
public readonly int CollectDataTimeout;
public readonly string UserName;
internal NamedPipeSocketState(IntPtr hPipe)
{
StringBuilder userName = new StringBuilder(256);
bool res = NamedPipeHelper.GetNamedPipeHandleState(
hPipe,
out State,
out CurrentInstances,
out MaxCollectionCount,
out CollectDataTimeout,
userName,
userName.Capacity
);
if (res)
{
UserName = userName.ToString();
}
else
{
throw new NamedPipeException();
}
}
}
}
#endif

View File

@@ -0,0 +1,143 @@
//
// System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeStream.cs
//
// Author: Robert Jordan (robertj@gmx.net)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_2_0
using System;
using System.IO;
using System.Runtime.Remoting.Messaging;
namespace System.Runtime.Remoting.Channels.Ipc.Win32
{
/// <summary>
/// Provides the underlying stream of data for local Named Pipe access.
/// </summary>
internal class NamedPipeStream : Stream
{
readonly NamedPipeSocket socket;
readonly bool ownsSocket;
/// <summary>
/// Creates a new instance of the NamedPipeStream class for the specified NamedPipeSocket.
/// </summary>
/// <param name="socket"></param>
public NamedPipeStream(NamedPipeSocket socket, bool ownsSocket)
{
this.socket = socket;
this.ownsSocket = ownsSocket;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Close()
{
if (ownsSocket) socket.Close();
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
return socket.Receive(buffer, offset, count);
}
delegate int ReadMethod(byte[] buffer, int offset, int count);
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return new ReadMethod(Read).BeginInvoke(buffer, offset, count, callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
{
AsyncResult ar = asyncResult as AsyncResult;
return ((ReadMethod)ar.AsyncDelegate).EndInvoke(ar);
}
public override void Write(byte[] buffer, int offset, int count)
{
int written = socket.Send(buffer, offset, count);
if (written != count)
throw new IOException("Cannot write data");
}
delegate void WriteMethod(byte[] buffer, int offset, int count);
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return new WriteMethod(Write).BeginInvoke(buffer, offset, count, callback, state);
}
public override void EndWrite(IAsyncResult asyncResult)
{
AsyncResult ar = asyncResult as AsyncResult;
((WriteMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
}
}
}
#endif