Abstract NamedPipes code for windows
This commit is contained in:
parent
12209176e7
commit
bacd2e534e
@ -2,7 +2,7 @@ using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
#if W32
|
||||
using sscs.communication.win.NamedPipes;
|
||||
using AppModule.NamedPipes;
|
||||
#endif
|
||||
using sscs.common;
|
||||
namespace sscs.communication
|
||||
|
@ -2,8 +2,9 @@ using System;
|
||||
using sscs.common;
|
||||
using sscs.constants;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
using sscs.communication.win.NamedPipes;
|
||||
using AppModule.InterProcessComm;
|
||||
using AppModule.NamedPipes;
|
||||
using sscs.communication.win;
|
||||
|
||||
namespace sscs.communication
|
||||
{
|
||||
@ -17,7 +18,7 @@ namespace sscs.communication
|
||||
|
||||
public WinCommunication()
|
||||
{
|
||||
PipeManager = new sscs.communication.win.PipeManager();
|
||||
PipeManager = new PipeManager();
|
||||
PipeManager.Initialize();
|
||||
}
|
||||
|
||||
@ -27,9 +28,7 @@ namespace sscs.communication
|
||||
//PipeManager = new PipeManager();
|
||||
//PipeManager.Initialize();
|
||||
//PipeManager.Start();
|
||||
PipeManager.Start();
|
||||
|
||||
|
||||
PipeManager.Start();
|
||||
}
|
||||
|
||||
public void CloseCommunicationEndPoint()
|
||||
|
@ -2,7 +2,8 @@ using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using sscs.communication.win.NamedPipes;
|
||||
using AppModule.NamedPipes;
|
||||
using sscs.communication.win;
|
||||
using sscs.common;
|
||||
using sscs.verbs;
|
||||
using sscs.constants;
|
||||
|
@ -1,72 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace sscs.communication.win.InterProcessComm {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Interface, which defines methods for a Channel Manager class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A Channel Manager is responsible for creating and maintaining channels for inter-process communication. The opened channels are meant to be reusable for performance optimization. Each channel needs to procees requests by calling the <see cref="AppModule.InterProcessComm.IChannelManager.HandleRequest">HandleRequest</see> method of the Channel Manager.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public interface IChannelManager {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Initializes the Channel Manager.
|
||||
/// </summary>
|
||||
#endregion
|
||||
void Initialize();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes all opened channels and stops the Channel Manager.
|
||||
/// </summary>
|
||||
#endregion
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Handles a request.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method currently caters for text based requests. XML strings can be used in case complex request structures are needed.
|
||||
/// </remarks>
|
||||
/// <param name="request">The incoming request.</param>
|
||||
/// <returns>The resulting response.</returns>
|
||||
#endregion
|
||||
string HandleRequest(string request);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Indicates whether the Channel Manager is in listening mode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property is left public so that other classes, like a server channel can start or stop listening based on the Channel Manager mode.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
bool Listen {get; set;}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Forces the Channel Manager to exit a sleeping mode and create a new channel.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Normally the Channel Manager will create a number of reusable channels, which will handle the incoming reqiests, and go into a sleeping mode. However if the request load is high, the Channel Manager needs to be asked to create additional channels.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
void WakeUp();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Removes an existing channel.
|
||||
/// </summary>
|
||||
/// <param name="param">A parameter identifying the channel.</param>
|
||||
#endregion
|
||||
void RemoveServerChannel(object param);
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace sscs.communication.win.InterProcessComm {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public interface IClientChannel : IDisposable {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
string HandleRequest(string request);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
string HandleRequest(Stream request);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
object HandleRequest(object request);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
IClientChannel Create();
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace sscs.communication.win.InterProcessComm {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public interface IInterProcessConnection : IDisposable {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
int NativeHandle{get;}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
void Connect();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
void Close();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
string Read();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
byte[] ReadBytes();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
#endregion
|
||||
void Write(string text);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
#endregion
|
||||
void WriteBytes(byte[] bytes);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
#endregion
|
||||
InterProcessConnectionState GetState();
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace sscs.communication.win.InterProcessComm {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public enum InterProcessConnectionState {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
NotSet = 0,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Error = 1,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Creating = 2,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Created = 3,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
WaitingForClient = 4,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
ConnectedToClient = 5,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
ConnectingToServer = 6,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
ConnectedToServer = 7,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Reading = 8,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
ReadData = 9,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Writing = 10,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
WroteData = 11,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Flushing = 12,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
FlushedData = 13,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Disconnecting = 14,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Disconnected = 15,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Closing = 16,
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
Closed = 17,
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace sscs.communication.win.InterProcessComm {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public class InterProcessIOException : Exception {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public bool IsServerAvailable = true;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public uint ErrorCode = 0;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
#endregion
|
||||
public InterProcessIOException(String text) : base(text) {
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
/// <param name="context"></param>
|
||||
#endregion
|
||||
protected InterProcessIOException(SerializationInfo info, StreamingContext context) : base(info, context) {
|
||||
}
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// An abstract class, which defines the methods for creating named pipes
|
||||
/// connections, reading and writing data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is inherited by
|
||||
/// <see cref="AppModule.NamedPipes.ClientPipeConnection">ClientPipeConnection</see>
|
||||
/// and <see cref="AppModule.NamedPipes.ServerPipeConnection">ServerPipeConnection</see>
|
||||
/// classes, used for client and server applications respectively, which communicate
|
||||
/// using NamesPipes.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public abstract class APipeConnection : IInterProcessConnection {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// A <see cref="AppModule.NamedPipes.PipeHandle">PipeHandle</see> object containing
|
||||
/// the native pipe handle.
|
||||
/// </summary>
|
||||
#endregion
|
||||
protected PipeHandle Handle = new PipeHandle();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The name of the named pipe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This name is used for creating a server pipe and connecting client ones to it.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
protected string Name;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Boolean field used by the IDisposable implementation.
|
||||
/// </summary>
|
||||
#endregion
|
||||
protected bool disposed = false;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The maximum bytes that will be read from the pipe connection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field could be used if the maximum length of the client message
|
||||
/// is known and we want to implement some security, which prevents the
|
||||
/// server from reading larger messages.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
protected int maxReadBytes;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Reads a message from the pipe connection and converts it to a string
|
||||
/// using the UTF8 encoding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See the <see cref="AppModule.NamedPipes.NamedPipeWrapper.Read">NamedPipeWrapper.Read</see>
|
||||
/// method for an explanation of the message format.
|
||||
/// </remarks>
|
||||
/// <returns>The UTF8 encoded string representation of the data.</returns>
|
||||
#endregion
|
||||
public string Read() {
|
||||
CheckIfDisposed();
|
||||
return NamedPipeWrapper.Read(Handle, maxReadBytes);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Reads a message from the pipe connection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See the <see cref="AppModule.NamedPipes.NamedPipeWrapper.ReadBytes">NamedPipeWrapper.ReadBytes</see>
|
||||
/// method for an explanation of the message format.
|
||||
/// </remarks>
|
||||
/// <returns>The bytes read from the pipe connection.</returns>
|
||||
#endregion
|
||||
public byte[] ReadBytes() {
|
||||
CheckIfDisposed();
|
||||
return NamedPipeWrapper.ReadBytes(Handle, maxReadBytes);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Writes a string to the pipe connection/
|
||||
/// </summary>
|
||||
/// <param name="text">The text to write.</param>
|
||||
#endregion
|
||||
public void Write(string text) {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.Write(Handle, text);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Writes an array of bytes to the pipe connection.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes array.</param>
|
||||
#endregion
|
||||
public void WriteBytes(byte[] bytes) {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.WriteBytes(Handle, bytes);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes the pipe connection.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public abstract void Close();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Connects a pipe connection.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public abstract void Connect();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Disposes a pipe connection by closing the underlying native handle.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public void Dispose() {
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Disposes a pipe connection by closing the underlying native handle.
|
||||
/// </summary>
|
||||
/// <param name="disposing">A boolean indicating how the method is called.</param>
|
||||
#endregion
|
||||
protected void Dispose(bool disposing) {
|
||||
if(!this.disposed) {
|
||||
NamedPipeWrapper.Close(this.Handle);
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Checks if the pipe connection is disposed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This check is done before performing any pipe operations.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public void CheckIfDisposed() {
|
||||
if(this.disposed) {
|
||||
throw new ObjectDisposedException("The Pipe Connection is disposed.");
|
||||
}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Gets the pipe connection state from the <see cref="AppModule.NamedPipes.PipeHandle">PipeHandle</see>
|
||||
/// object.
|
||||
/// </summary>
|
||||
/// <returns>The pipe connection state.</returns>
|
||||
#endregion
|
||||
public InterProcessConnectionState GetState() {
|
||||
CheckIfDisposed();
|
||||
return this.Handle.State;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Retrieved the operating system native handle for the pipe connection.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public int NativeHandle {
|
||||
get {
|
||||
CheckIfDisposed();
|
||||
return (int)this.Handle.Handle;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetLocalUserID(ref int lowPart, ref int highPart, ref string sSIDString)
|
||||
{
|
||||
return NamedPipeWrapper.GetLocalUserID(this.Handle, ref lowPart, ref highPart, ref sSIDString);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Used by client applications to communicate with server ones by using named pipes.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public sealed class ClientPipeConnection : APipeConnection {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The network name of the server where the server pipe is created.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If "." is used as a server name then the pipe is connected to the local machine.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
private string Server = ".";
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes a client named pipe connection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A client pipe connection is closed by closing the underlying pipe handle.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public override void Close() {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.Close(this.Handle);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Connects a client pipe to an existing server one.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public override void Connect() {
|
||||
CheckIfDisposed();
|
||||
this.Handle = NamedPipeWrapper.ConnectToPipe(this.Name, this.Server);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Attempts to establish a connection to the a server named pipe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the attempt is successful the method creates the
|
||||
/// <see cref="AppModule.NamedPipes.PipeHandle">PipeHandle</see> object
|
||||
/// and assigns it to the <see cref="AppModule.NamedPipes.APipeConnection.Handle">Handle</see>
|
||||
/// field.<br/><br/>
|
||||
/// This method is used when it is not known whether a server pipe already exists.
|
||||
/// </remarks>
|
||||
/// <returns>True if a connection is established.</returns>
|
||||
#endregion
|
||||
public bool TryConnect() {
|
||||
CheckIfDisposed();
|
||||
bool ReturnVal = NamedPipeWrapper.TryConnectToPipe(this.Name, this.Server, out this.Handle);
|
||||
|
||||
return ReturnVal;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates an instance of the ClientPipeConnection assuming that the server pipe
|
||||
/// is created on the same machine.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The maximum bytes to read from the client is set to be Int32.MaxValue.
|
||||
/// </remarks>
|
||||
/// <param name="name">The name of the server pipe.</param>
|
||||
#endregion
|
||||
public ClientPipeConnection(string name) {
|
||||
this.Name = name;
|
||||
this.Server = ".";
|
||||
this.maxReadBytes = Int32.MaxValue;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates an instance of the ClientPipeConnection specifying the network name
|
||||
/// of the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The maximum bytes to read from the client is set to be Int32.MaxValue.
|
||||
/// </remarks>
|
||||
/// <param name="name">The name of the server pipe.</param>
|
||||
/// <param name="server">The network name of the machine, where the server pipe is created.</param>
|
||||
#endregion
|
||||
public ClientPipeConnection(string name, string server) {
|
||||
this.Name = name;
|
||||
this.Server = server;
|
||||
this.maxReadBytes = Int32.MaxValue;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Object destructor.
|
||||
/// </summary>
|
||||
#endregion
|
||||
~ClientPipeConnection() {
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// This exception is thrown by named pipes communication methods.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public class NamedPipeIOException : InterProcessIOException {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a NamedPipeIOException instance.
|
||||
/// </summary>
|
||||
/// <param name="text">The error message text.</param>
|
||||
#endregion
|
||||
public NamedPipeIOException(String text) : base(text) {
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a NamedPipeIOException instance.
|
||||
/// </summary>
|
||||
/// <param name="text">The error message text.</param>
|
||||
/// <param name="errorCode">The native error code.</param>
|
||||
#endregion
|
||||
public NamedPipeIOException(String text, uint errorCode) : base(text) {
|
||||
this.ErrorCode = errorCode;
|
||||
if (errorCode == NamedPipeNative.ERROR_CANNOT_CONNECT_TO_PIPE) {
|
||||
this.IsServerAvailable = false;
|
||||
}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a NamedPipeIOException instance.
|
||||
/// </summary>
|
||||
/// <param name="info">The serialization information.</param>
|
||||
/// <param name="context">The streaming context.</param>
|
||||
#endregion
|
||||
protected NamedPipeIOException(SerializationInfo info, StreamingContext context) : base(info, context) {
|
||||
}
|
||||
}
|
||||
}
|
@ -1,641 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// This utility class exposes kernel32.dll methods for named pipes communication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the following links for complete information about the exposed methods:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ipc/base/pipe_functions.asp" target="_blank">Named Pipe Functions</a></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description><a href="http://msdn.microsoft.com/library/en-us/fileio/base/file_management_functions.asp" target="_blank">File Management Functions</a></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/handle_and_object_functions.asp" target="_blank">Handle and Object Functions</a></description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp" target="_blank">System Error Codes</a></description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
#endregion
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public sealed class NamedPipeNative {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Outbound pipe access.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_ACCESS_OUTBOUND = 0x00000002;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Duplex pipe access.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_ACCESS_DUPLEX = 0x00000003;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Inbound pipe access.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_ACCESS_INBOUND = 0x00000001;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe blocking mode.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_WAIT = 0x00000000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe non-blocking mode.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_NOWAIT = 0x00000001;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe read mode of type Byte.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_READMODE_BYTE = 0x00000000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe read mode of type Message.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_READMODE_MESSAGE = 0x00000002;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Byte pipe type.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_TYPE_BYTE = 0x00000000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Message pipe type.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_TYPE_MESSAGE = 0x00000004;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe client end.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_CLIENT_END = 0x00000000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Pipe server end.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_SERVER_END = 0x00000001;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Unlimited server pipe instances.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint PIPE_UNLIMITED_INSTANCES = 255;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Waits indefinitely when connecting to a pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Does not wait for the named pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint NMPWAIT_NOWAIT = 0x00000001;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Uses the default time-out specified in a call to the CreateNamedPipe method.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint GENERIC_READ = (0x80000000);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Generic write access to the pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint GENERIC_WRITE = (0x40000000);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Generic execute access to the pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint GENERIC_EXECUTE = (0x20000000);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Read, write, and execute access.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint GENERIC_ALL = (0x10000000);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Create new file. Fails if the file exists.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint CREATE_NEW = 1;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Create new file. Overrides an existing file.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint CREATE_ALWAYS = 2;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Open existing file.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint OPEN_EXISTING = 3;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Open existing file. If the file does not exist, creates it.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint OPEN_ALWAYS = 4;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Opens the file and truncates it so that its size is zero bytes.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const uint TRUNCATE_EXISTING = 5;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Invalid operating system handle.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const int INVALID_HANDLE_VALUE = -1;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The operation completed successfully.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_SUCCESS = 0;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The system cannot find the file specified.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_CANNOT_CONNECT_TO_PIPE = 2;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// All pipe instances are busy.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_PIPE_BUSY = 231;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The pipe is being closed.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_NO_DATA = 232;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// No process is on the other end of the pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_PIPE_NOT_CONNECTED = 233;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// More data is available.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_MORE_DATA = 234;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// There is a process on other end of the pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_PIPE_CONNECTED = 535;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Waiting for a process to open the other end of the pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const ulong ERROR_PIPE_LISTENING = 536;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
#endregion
|
||||
public const int TOKEN_QUERY = 0X00000008;
|
||||
|
||||
public enum TOKEN_INFORMATION_CLASS
|
||||
{
|
||||
TokenUser = 1,
|
||||
TokenGroups,
|
||||
TokenPrivileges,
|
||||
TokenOwner,
|
||||
TokenPrimaryGroup,
|
||||
TokenDefaultDacl,
|
||||
TokenSource,
|
||||
TokenType,
|
||||
TokenImpersonationLevel,
|
||||
TokenStatistics,
|
||||
TokenRestrictedSids,
|
||||
TokenSessionId
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TOKEN_USER
|
||||
{
|
||||
public _SID_AND_ATTRIBUTES User;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct _SID_AND_ATTRIBUTES
|
||||
{
|
||||
public IntPtr Sid;
|
||||
public int Attributes;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct _LUID
|
||||
{
|
||||
public int LowPart ;
|
||||
public int HighPart;
|
||||
} //LUID, *PLUID;
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TOKEN_STATISTICS
|
||||
{
|
||||
public _LUID TokenId;
|
||||
public _LUID AuthenticationId;
|
||||
public int ExpirationTime;
|
||||
public int TokenType; // enum ini in 1 TOKEN_TYPE
|
||||
public int ImpersonationLevel; //SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
||||
public int DynamicCharged; ////DWORD
|
||||
public int DynamicAvailable; //DWORD
|
||||
public int GroupCount; //DWORD
|
||||
public int PrivilegeCount; //DWORD
|
||||
public _LUID ModifiedId;
|
||||
}// TOKEN_STATISTICS, *PTOKEN_STATISTICS;
|
||||
|
||||
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates an instance of a named pipe and returns a handle for
|
||||
/// subsequent pipe operations.
|
||||
/// </summary>
|
||||
/// <param name="lpName">Pointer to the null-terminated string that
|
||||
/// uniquely identifies the pipe.</param>
|
||||
/// <param name="dwOpenMode">Pipe access mode, the overlapped mode,
|
||||
/// the write-through mode, and the security access mode of the pipe handle.</param>
|
||||
/// <param name="dwPipeMode">Type, read, and wait modes of the pipe handle.</param>
|
||||
/// <param name="nMaxInstances">Maximum number of instances that can be
|
||||
/// created for this pipe.</param>
|
||||
/// <param name="nOutBufferSize">Number of bytes to reserve for the output buffer.</param>
|
||||
/// <param name="nInBufferSize">Number of bytes to reserve for the input buffer.</param>
|
||||
/// <param name="nDefaultTimeOut">Default time-out value, in milliseconds.</param>
|
||||
/// <param name="pipeSecurityDescriptor">Pointer to a
|
||||
/// <see cref="AppModule.NamedPipes.SecurityAttributes">SecurityAttributes</see>
|
||||
/// object that specifies a security descriptor for the new named pipe.</param>
|
||||
/// <returns>If the function succeeds, the return value is a handle
|
||||
/// to the server end of a named pipe instance.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr CreateNamedPipe(
|
||||
String lpName, // pipe name
|
||||
uint dwOpenMode, // pipe open mode
|
||||
uint dwPipeMode, // pipe-specific modes
|
||||
uint nMaxInstances, // maximum number of instances
|
||||
uint nOutBufferSize, // output buffer size
|
||||
uint nInBufferSize, // input buffer size
|
||||
uint nDefaultTimeOut, // time-out interval
|
||||
IntPtr pipeSecurityDescriptor // SD
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Enables a named pipe server process to wait for a client
|
||||
/// process to connect to an instance of a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to the server end of a named pipe instance.</param>
|
||||
/// <param name="lpOverlapped">Pointer to an
|
||||
/// <see cref="AppModule.NamedPipes.Overlapped">Overlapped</see> object.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool ConnectNamedPipe(
|
||||
IntPtr hHandle, // handle to named pipe
|
||||
Overlapped lpOverlapped // overlapped structure
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Connects to a message-type pipe (and waits if an instance of the
|
||||
/// pipe is not available), writes to and reads from the pipe, and then closes the pipe.
|
||||
/// </summary>
|
||||
/// <param name="lpNamedPipeName">Pointer to a null-terminated string
|
||||
/// specifying the pipe name.</param>
|
||||
/// <param name="lpInBuffer">Pointer to the buffer containing the data written
|
||||
/// to the pipe.</param>
|
||||
/// <param name="nInBufferSize">Size of the write buffer, in bytes.</param>
|
||||
/// <param name="lpOutBuffer">Pointer to the buffer that receives the data
|
||||
/// read from the pipe.</param>
|
||||
/// <param name="nOutBufferSize">Size of the read buffer, in bytes.</param>
|
||||
/// <param name="lpBytesRead">Pointer to a variable that receives the number
|
||||
/// of bytes read from the pipe.</param>
|
||||
/// <param name="nTimeOut">Number of milliseconds to wait for the
|
||||
/// named pipe to be available.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool CallNamedPipe(
|
||||
string lpNamedPipeName,
|
||||
byte[] lpInBuffer,
|
||||
uint nInBufferSize,
|
||||
byte[] lpOutBuffer,
|
||||
uint nOutBufferSize,
|
||||
byte[] lpBytesRead,
|
||||
int nTimeOut
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates or opens a file, directory, physical disk, volume, console buffer,
|
||||
/// tape drive, communications resource, mailslot, or named pipe.
|
||||
/// </summary>
|
||||
/// <param name="lpFileName">Pointer to a null-terminated string that
|
||||
/// specifies the name of the object to create or open.</param>
|
||||
/// <param name="dwDesiredAccess">Access to the object (reading, writing, or both).</param>
|
||||
/// <param name="dwShareMode">Sharing mode of the object (reading, writing, both, or neither).</param>
|
||||
/// <param name="attr">Pointer to a
|
||||
/// <see cref="AppModule.NamedPipes.SecurityAttributes">SecurityAttributes</see>
|
||||
/// object that determines whether the returned handle can be inherited
|
||||
/// by child processes.</param>
|
||||
/// <param name="dwCreationDisposition">Action to take on files that exist,
|
||||
/// and which action to take when files do not exist.</param>
|
||||
/// <param name="dwFlagsAndAttributes">File attributes and flags.</param>
|
||||
/// <param name="hTemplateFile">Handle to a template file, with the GENERIC_READ access right.</param>
|
||||
/// <returns>If the function succeeds, the return value is an open handle to the specified file.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr CreateFile(
|
||||
String lpFileName, // file name
|
||||
uint dwDesiredAccess, // access mode
|
||||
uint dwShareMode, // share mode
|
||||
SecurityAttributes attr, // SD
|
||||
uint dwCreationDisposition, // how to create
|
||||
uint dwFlagsAndAttributes, // file attributes
|
||||
uint hTemplateFile); // handle to template file
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Reads data from a file, starting at the position indicated by the file pointer.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to the file to be read.</param>
|
||||
/// <param name="lpBuffer">Pointer to the buffer that receives the data read from the file.</param>
|
||||
/// <param name="nNumberOfBytesToRead">Number of bytes to be read from the file.</param>
|
||||
/// <param name="lpNumberOfBytesRead">Pointer to the variable that receives the number of bytes read.</param>
|
||||
/// <param name="lpOverlapped">Pointer to an
|
||||
/// <see cref="AppModule.NamedPipes.Overlapped">Overlapped</see> object.</param>
|
||||
/// <returns>The ReadFile function returns when one of the following
|
||||
/// conditions is met: a write operation completes on the write end of
|
||||
/// the pipe, the number of bytes requested has been read, or an error occurs.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool ReadFile(
|
||||
IntPtr hHandle, // handle to file
|
||||
byte[] lpBuffer, // data buffer
|
||||
uint nNumberOfBytesToRead, // number of bytes to read
|
||||
byte[] lpNumberOfBytesRead, // number of bytes read
|
||||
uint lpOverlapped // overlapped buffer
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Writes data to a file at the position specified by the file pointer.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to the file.</param>
|
||||
/// <param name="lpBuffer">Pointer to the buffer containing the data to be written to the file.</param>
|
||||
/// <param name="nNumberOfBytesToWrite"></param>
|
||||
/// <param name="lpNumberOfBytesWritten">Pointer to the variable that receives the number of bytes written.</param>
|
||||
/// <param name="lpOverlapped">Pointer to an
|
||||
/// <see cref="AppModule.NamedPipes.Overlapped">Overlapped</see> object.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool WriteFile(
|
||||
IntPtr hHandle, // handle to file
|
||||
byte[] lpBuffer, // data buffer
|
||||
uint nNumberOfBytesToWrite, // number of bytes to write
|
||||
byte[] lpNumberOfBytesWritten, // number of bytes written
|
||||
uint lpOverlapped // overlapped buffer
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Retrieves information about a specified named pipe.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to the named pipe for which information is wanted.</param>
|
||||
/// <param name="lpState">Pointer to a variable that indicates the current
|
||||
/// state of the handle.</param>
|
||||
/// <param name="lpCurInstances">Pointer to a variable that receives the
|
||||
/// number of current pipe instances.</param>
|
||||
/// <param name="lpMaxCollectionCount">Pointer to a variable that receives
|
||||
/// the maximum number of bytes to be collected on the client's computer
|
||||
/// before transmission to the server.</param>
|
||||
/// <param name="lpCollectDataTimeout">Pointer to a variable that receives
|
||||
/// the maximum time, in milliseconds, that can pass before a remote named
|
||||
/// pipe transfers information over the network.</param>
|
||||
/// <param name="lpUserName">Pointer to a buffer that receives the
|
||||
/// null-terminated string containing the user name string associated
|
||||
/// with the client application. </param>
|
||||
/// <param name="nMaxUserNameSize">Size of the buffer specified by the
|
||||
/// lpUserName parameter.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool GetNamedPipeHandleState(
|
||||
IntPtr hHandle,
|
||||
IntPtr lpState,
|
||||
ref uint lpCurInstances,
|
||||
IntPtr lpMaxCollectionCount,
|
||||
IntPtr lpCollectDataTimeout,
|
||||
IntPtr lpUserName,
|
||||
IntPtr nMaxUserNameSize
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Cancels all pending input and output (I/O) operations that were
|
||||
/// issued by the calling thread for the specified file handle.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to a file.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool CancelIo(
|
||||
IntPtr hHandle
|
||||
);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Waits until either a time-out interval elapses or an instance
|
||||
/// of the specified named pipe is available for connection.
|
||||
/// </summary>
|
||||
/// <param name="name">Pointer to a null-terminated string that specifies
|
||||
/// the name of the named pipe.</param>
|
||||
/// <param name="timeout">Number of milliseconds that the function will
|
||||
/// wait for an instance of the named pipe to be available.</param>
|
||||
/// <returns>If an instance of the pipe is available before the
|
||||
/// time-out interval elapses, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool WaitNamedPipe(
|
||||
String name,
|
||||
int timeout);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Retrieves the calling thread's last-error code value.
|
||||
/// </summary>
|
||||
/// <returns>The return value is the calling thread's last-error code value.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetLastError();
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Flushes the buffers of the specified file and causes all buffered data to be written to the file.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to an open file.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool FlushFileBuffers(
|
||||
IntPtr hHandle);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Disconnects the server end of a named pipe instance from a client process.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to an instance of a named pipe.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool DisconnectNamedPipe(
|
||||
IntPtr hHandle);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Sets the read mode and the blocking mode of the specified named pipe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the specified handle is to the client end of a named pipe and if
|
||||
/// the named pipe server process is on a remote computer, the function
|
||||
/// can also be used to control local buffering.
|
||||
/// </remarks>
|
||||
/// <param name="hHandle">Handle to the named pipe instance.</param>
|
||||
/// <param name="mode">Pointer to a variable that supplies the new mode.</param>
|
||||
/// <param name="cc">Pointer to a variable that specifies the maximum
|
||||
/// number of bytes collected on the client computer before
|
||||
/// transmission to the server.</param>
|
||||
/// <param name="cd">Pointer to a variable that specifies the
|
||||
/// maximum time, in milliseconds, that can pass before a remote
|
||||
/// named pipe transfers information over the network.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool SetNamedPipeHandleState(
|
||||
IntPtr hHandle,
|
||||
ref uint mode,
|
||||
IntPtr cc,
|
||||
IntPtr cd);
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes an open object handle.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to an open object.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool CloseHandle(
|
||||
IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
|
||||
// native for named pipes
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes an open object handle.
|
||||
/// </summary>
|
||||
/// <param name="hHandle">Handle to an open object.</param>
|
||||
/// <returns>If the function succeeds, the return value is nonzero.</returns>
|
||||
#endregion
|
||||
[DllImport("advapi32" )]
|
||||
public static extern int ImpersonateNamedPipeClient(
|
||||
IntPtr hHandle);
|
||||
|
||||
[DllImport("advapi32" )]
|
||||
public static extern bool RevertToSelf();
|
||||
|
||||
[DllImport("advapi32", SetLastError=true)]
|
||||
public static extern bool OpenThreadToken(
|
||||
IntPtr hThread,
|
||||
uint desiredInfo,
|
||||
bool openAsSelf,
|
||||
out IntPtr TokenHandle); // handle to open access token
|
||||
|
||||
[DllImport("advapi32")]
|
||||
public static extern bool OpenProcessToken(
|
||||
IntPtr ProcessHandle, // handle to process
|
||||
int DesiredAccess, // desired access to process
|
||||
ref IntPtr TokenHandle // handle to open access token
|
||||
);
|
||||
|
||||
[DllImport("advapi32", CharSet=CharSet.Auto)]
|
||||
public static extern bool GetTokenInformation(
|
||||
IntPtr hToken,
|
||||
TOKEN_INFORMATION_CLASS tokenInfoClass,
|
||||
IntPtr TokenInformation,
|
||||
int tokeInfoLength,
|
||||
ref int reqLength);
|
||||
|
||||
|
||||
[DllImport("advapi32", CharSet=CharSet.Auto)]
|
||||
public static extern bool LookupAccountSid
|
||||
(
|
||||
[In,MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, // name of local or remote computer
|
||||
IntPtr pSid, // security identifier
|
||||
StringBuilder Account, // account name buffer
|
||||
ref int cbName, // size of account name buffer
|
||||
StringBuilder DomainName, // domain name
|
||||
ref int cbDomainName, // size of domain name buffer
|
||||
ref int peUse // SID type
|
||||
// ref _SID_NAME_USE peUse // SID type
|
||||
);
|
||||
|
||||
[DllImport("advapi32", CharSet=CharSet.Auto)]
|
||||
public static extern bool ConvertSidToStringSid(
|
||||
IntPtr pSID,
|
||||
[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
|
||||
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Private constructor.
|
||||
/// </summary>
|
||||
#endregion
|
||||
private NamedPipeNative() {}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// This class is used as a dummy parameter only.
|
||||
/// </summary>
|
||||
#endregion
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class SecurityAttributes {
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// This class is used as a dummy parameter only.
|
||||
/// </summary>
|
||||
#endregion
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class Overlapped {
|
||||
}
|
||||
}
|
@ -1,628 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using HANDLE = System.IntPtr;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes
|
||||
{
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// A utility class that exposes named pipes operations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class uses the exposed exposed kernel32.dll methods by the
|
||||
/// <see cref="AppModule.NamedPipes.NamedPipeNative">NamedPipeNative</see> class
|
||||
/// to provided controlled named pipe functionality.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public sealed class NamedPipeWrapper
|
||||
{
|
||||
|
||||
public const int TOKEN_QUERY = 0X00000008;
|
||||
|
||||
const int ERROR_NO_MORE_ITEMS = 259;
|
||||
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The number of retries when creating a pipe or connecting to a pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
private const int ATTEMPTS = 2;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Wait time for the
|
||||
/// <see cref="AppModule.NamedPipes.NamedPipeNative.WaitNamedPipe">NamedPipeNative.WaitNamedPipe</see>
|
||||
/// operation.
|
||||
/// </summary>
|
||||
#endregion
|
||||
private const int WAIT_TIME = 5000;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Reads a string from a named pipe using the UTF8 encoding.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
/// <param name="maxBytes">The maximum bytes to read.</param>
|
||||
/// <returns>A UTF8 string.</returns>
|
||||
/// <remarks>This function uses
|
||||
/// <see cref="AppModule.NamedPipes.NamedPipeWrapper.ReadBytes">AppModule.NamedPipes.ReadBytes</see>
|
||||
/// to read the bytes from the pipe and then converts them to string.<br/><br/>
|
||||
/// The first four bytes of the pipe data are expected to contain
|
||||
/// the data length of the message. This method first reads those four
|
||||
/// bytes and converts them to integer. It then continues to read from the pipe using
|
||||
/// the extracted data length.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public static string Read(PipeHandle handle, int maxBytes)
|
||||
{
|
||||
string returnVal = "";
|
||||
byte[] bytes = ReadBytes(handle, maxBytes);
|
||||
if (bytes != null)
|
||||
{
|
||||
returnVal = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Reads the bytes from a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
/// <param name="maxBytes">The maximum bytes to read.</param>
|
||||
/// <returns>An array of bytes.</returns>
|
||||
/// <remarks>This method expects that the first four bytes in the pipe define
|
||||
/// the length of the data to read. If the data length is greater than
|
||||
/// <b>maxBytes</b> the method returns null.<br/><br/>
|
||||
/// The first four bytes of the pipe data are expected to contain
|
||||
/// the data length of the message. This method first reads those four
|
||||
/// bytes and converts them to integer. It then continues to read from the pipe using
|
||||
/// the extracted data length.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public static byte[] ReadBytes(PipeHandle handle, int maxBytes)
|
||||
{
|
||||
byte[] numReadWritten = new byte[4];
|
||||
byte[] intBytes = new byte[4];
|
||||
byte[] msgBytes = null;
|
||||
int len;
|
||||
|
||||
// Set the Handle state to Reading
|
||||
handle.State = InterProcessConnectionState.Reading;
|
||||
// Read the first four bytes and convert them to integer
|
||||
bool bReadSuccessful = true;
|
||||
|
||||
try
|
||||
{
|
||||
bReadSuccessful = NamedPipeNative.ReadFile(handle.Handle, intBytes, 4, numReadWritten, 0);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Console.WriteLine("Error on ReadFile "+e.ToString());
|
||||
}
|
||||
|
||||
if (bReadSuccessful)
|
||||
{
|
||||
len = BitConverter.ToInt32(intBytes, 0);
|
||||
msgBytes = new byte[len];
|
||||
// Read the rest of the data
|
||||
if (!NamedPipeNative.ReadFile(handle.Handle, msgBytes, (uint)len, numReadWritten, 0))
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error reading from pipe. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error reading from pipe. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
handle.State = InterProcessConnectionState.ReadData;
|
||||
if (len > maxBytes)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return msgBytes;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Writes a string to a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
/// <param name="text">The text to write to the pipe.</param>
|
||||
/// <remarks>This method converts the text into an array of bytes, using the
|
||||
/// UTF8 encoding and the uses
|
||||
/// <see cref="AppModule.NamedPipes.NamedPipeWrapper.WriteBytes">AppModule.NamedPipes.WriteBytes</see>
|
||||
/// to write to the pipe.<br/><br/>
|
||||
/// When writing to a pipe the method first writes four bytes that define the data length.
|
||||
/// It then writes the whole message.</remarks>
|
||||
#endregion
|
||||
public static void Write(PipeHandle handle, string text)
|
||||
{
|
||||
WriteBytes(handle, System.Text.Encoding.UTF8.GetBytes(text));
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Writes an array of bytes to a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
/// <param name="bytes">The bytes to write.</param>
|
||||
/// <remarks>If we try bytes array we attempt to write is empty then this method write a space character to the pipe. This is necessary because the other end of the pipe uses a blocking Read operation so we must write someting.<br/><br/>
|
||||
/// The bytes length is restricted by the <b>maxBytes</b> parameter, which is done primarily for security reasons.<br/><br/>
|
||||
/// When writing to a pipe the method first writes four bytes that define the data length.
|
||||
/// It then writes the whole message.</remarks>
|
||||
#endregion
|
||||
public static void WriteBytes(PipeHandle handle, byte[] bytes)
|
||||
{
|
||||
byte[] numReadWritten = new byte[4];
|
||||
uint len;
|
||||
|
||||
if (bytes == null)
|
||||
{
|
||||
bytes = new byte[0];
|
||||
}
|
||||
if (bytes.Length == 0)
|
||||
{
|
||||
bytes = new byte[1];
|
||||
bytes = System.Text.Encoding.UTF8.GetBytes(" ");
|
||||
}
|
||||
// Get the message length
|
||||
len = (uint)bytes.Length;
|
||||
handle.State = InterProcessConnectionState.Writing;
|
||||
// Write four bytes that define the message length
|
||||
if (NamedPipeNative.WriteFile(handle.Handle, BitConverter.GetBytes(len), 4, numReadWritten, 0)) {
|
||||
// Write the whole message
|
||||
if (!NamedPipeNative.WriteFile(handle.Handle, bytes, len, numReadWritten, 0)) {
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error writing to pipe. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
else {
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error writing to pipe. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
handle.State = InterProcessConnectionState.Flushing;
|
||||
Flush(handle);
|
||||
handle.State = InterProcessConnectionState.FlushedData;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Tries to connect to a named pipe on the same machine.
|
||||
/// </summary>
|
||||
/// <param name="pipeName">The name of the pipe.</param>
|
||||
/// <param name="handle">The resulting pipe handle.</param>
|
||||
/// <returns>Return true if the attempt succeeds.</returns>
|
||||
/// <remarks>This method is used mainly when stopping the pipe server. It unblocks the existing pipes, which wait for client connection.</remarks>
|
||||
#endregion
|
||||
public static bool TryConnectToPipe(string pipeName, out PipeHandle handle)
|
||||
{
|
||||
return TryConnectToPipe(pipeName, ".", out handle);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Tries to connect to a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="pipeName">The name of the pipe.</param>
|
||||
/// <param name="serverName">The name of the server.</param>
|
||||
/// <param name="handle">The resulting pipe handle.</param>
|
||||
/// <returns>Return true if the attempt succeeds.</returns>
|
||||
/// <remarks>This method is used mainly when stopping the pipe server. It unblocks the existing pipes, which wait for client connection.</remarks>
|
||||
#endregion
|
||||
public static bool TryConnectToPipe(string pipeName, string serverName, out PipeHandle handle)
|
||||
{
|
||||
handle = new PipeHandle();
|
||||
// Build the pipe name string
|
||||
string name = @"\\" + serverName + @"\pipe\" + pipeName;
|
||||
handle.State = InterProcessConnectionState.ConnectingToServer;
|
||||
// Try to connect to a server pipe
|
||||
handle.Handle = NamedPipeNative.CreateFile(name, NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, 0, null, NamedPipeNative.OPEN_EXISTING, 0, 0);
|
||||
if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.ConnectedToServer;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Connects to a server named pipe on the same machine.
|
||||
/// </summary>
|
||||
/// <param name="pipeName">The pipe name.</param>
|
||||
/// <returns>The pipe handle, which also contains the pipe state.</returns>
|
||||
/// <remarks>This method is used by clients to establish a pipe connection with a server pipe.</remarks>
|
||||
#endregion
|
||||
public static PipeHandle ConnectToPipe(string pipeName)
|
||||
{
|
||||
return ConnectToPipe(pipeName, ".");
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Connects to a server named pipe.
|
||||
/// </summary>
|
||||
/// <param name="pipeName">The pipe name.</param>
|
||||
/// <param name="serverName">The server name.</param>
|
||||
/// <returns>The pipe handle, which also contains the pipe state.</returns>
|
||||
/// <remarks>This method is used by clients to establish a pipe connection with a server pipe.</remarks>
|
||||
#endregion
|
||||
public static PipeHandle ConnectToPipe(string pipeName, string serverName)
|
||||
{
|
||||
PipeHandle handle = new PipeHandle();
|
||||
// Build the name of the pipe.
|
||||
string name = @"\\" + serverName + @"\PIPE\" + pipeName;
|
||||
|
||||
for (int i = 1; i<=ATTEMPTS; i++)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.ConnectingToServer;
|
||||
// Try to connect to the server
|
||||
handle.Handle = NamedPipeNative.CreateFile(name, NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE, 0, null, NamedPipeNative.OPEN_EXISTING, 0, 0);
|
||||
if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// The client managed to connect to the server pipe
|
||||
handle.State = InterProcessConnectionState.ConnectedToServer;
|
||||
// Set the read mode of the pipe channel
|
||||
uint mode = NamedPipeNative.PIPE_READMODE_MESSAGE;
|
||||
if (NamedPipeNative.SetNamedPipeHandleState(handle.Handle, ref mode, IntPtr.Zero, IntPtr.Zero))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (i >= ATTEMPTS)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error setting read mode on pipe " + name + " . Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
if (i >= ATTEMPTS)
|
||||
{
|
||||
if (NamedPipeNative.GetLastError() != NamedPipeNative.ERROR_PIPE_BUSY)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
// After a certain number of unsuccessful attempt raise an exception
|
||||
throw new NamedPipeIOException("Error connecting to pipe " + name + " . Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Pipe " + name + " is too busy. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The pipe is busy so lets wait for some time and try again
|
||||
if (NamedPipeNative.GetLastError() == NamedPipeNative.ERROR_PIPE_BUSY)
|
||||
NamedPipeNative.WaitNamedPipe(name, WAIT_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a server named pipe.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the pipe.</param>
|
||||
/// <param name="outBuffer">The size of the outbound buffer.</param>
|
||||
/// <param name="inBuffer">The size of the inbound buffer.</param>
|
||||
/// <returns>The pipe handle.</returns>
|
||||
#endregion
|
||||
public static PipeHandle Create(string name, uint outBuffer, uint inBuffer)
|
||||
{
|
||||
if ((name.IndexOf("pipe") < 0) && (name.IndexOf("PIPE") < 0))
|
||||
name = @"\\.\pipe\" + name;
|
||||
|
||||
PipeHandle handle = new PipeHandle();
|
||||
for (int i = 1; i<=ATTEMPTS; i++)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Creating;
|
||||
handle.Handle = NamedPipeNative.CreateNamedPipe(
|
||||
name,
|
||||
NamedPipeNative.PIPE_ACCESS_DUPLEX,
|
||||
NamedPipeNative.PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_READMODE_MESSAGE | NamedPipeNative.PIPE_WAIT,
|
||||
NamedPipeNative.PIPE_UNLIMITED_INSTANCES,
|
||||
outBuffer,
|
||||
inBuffer,
|
||||
NamedPipeNative.NMPWAIT_WAIT_FOREVER,
|
||||
IntPtr.Zero);
|
||||
if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Created;
|
||||
break;
|
||||
}
|
||||
if (i >= ATTEMPTS)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error creating named pipe " + name + " . Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Starts waiting for client connections.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Blocks the current execution until a client pipe attempts to establish a connection.
|
||||
/// </remarks>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
#endregion
|
||||
public static void Connect(PipeHandle handle)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.WaitingForClient;
|
||||
bool connected = NamedPipeNative.ConnectNamedPipe(handle.Handle, null);
|
||||
handle.State = InterProcessConnectionState.ConnectedToClient;
|
||||
if (!connected && NamedPipeNative.GetLastError() != NamedPipeNative.ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Error;
|
||||
throw new NamedPipeIOException("Error connecting pipe. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Returns the number of instances of a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
/// <returns>The number of instances.</returns>
|
||||
#endregion
|
||||
public static uint NumberPipeInstances(PipeHandle handle)
|
||||
{
|
||||
uint curInstances = 0;
|
||||
|
||||
if (NamedPipeNative.GetNamedPipeHandleState(handle.Handle, IntPtr.Zero, ref curInstances, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
|
||||
{
|
||||
return curInstances;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NamedPipeIOException("Error getting the pipe state. Internal error: " + NamedPipeNative.GetLastError().ToString(), NamedPipeNative.GetLastError());
|
||||
}
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes a named pipe and releases the native handle.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
#endregion
|
||||
public static void Close(PipeHandle handle)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Closing;
|
||||
NamedPipeNative.CloseHandle(handle.Handle);
|
||||
handle.Handle = IntPtr.Zero;
|
||||
handle.State = InterProcessConnectionState.Closed;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Flushes all the data in a named pipe.
|
||||
/// </summary>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
#endregion
|
||||
public static void Flush(PipeHandle handle)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Flushing;
|
||||
NamedPipeNative.FlushFileBuffers(handle.Handle);
|
||||
handle.State = InterProcessConnectionState.FlushedData;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Disconnects a server named pipe from the client.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Server pipes can be reused by first disconnecting them from the client and then
|
||||
/// calling the <see cref="AppModule.NamedPipes.NamedPipeWrapper.Connect">Connect</see>
|
||||
/// method to start listening. This improves the performance as it is not necessary
|
||||
/// to create new pipe handles.
|
||||
/// </remarks>
|
||||
/// <param name="handle">The pipe handle.</param>
|
||||
#endregion
|
||||
public static void Disconnect(PipeHandle handle)
|
||||
{
|
||||
handle.State = InterProcessConnectionState.Disconnecting;
|
||||
NamedPipeNative.DisconnectNamedPipe(handle.Handle);
|
||||
handle.State = InterProcessConnectionState.Disconnected;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Private constructor.
|
||||
/// </summary>
|
||||
#endregion
|
||||
private NamedPipeWrapper() {}
|
||||
|
||||
|
||||
// Client USERID stuff
|
||||
// 1. call ImpersonateNamedPipeClient(hPipe)
|
||||
// 2. call OpenThreadToken(GetCurrentThread(),
|
||||
// TOKEN_QUERY | TOKEN_QUERY_SOURCE,
|
||||
// FALSE,
|
||||
// phUserToken);
|
||||
|
||||
public static int ImpersonateNamePipeClient(IntPtr hPipeHandle)
|
||||
{
|
||||
int rcode = NamedPipeNative.ImpersonateNamedPipeClient(hPipeHandle);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
static int PerformDump(HANDLE token)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
NamedPipeNative.TOKEN_USER tokUser;
|
||||
const int bufLength = 256;
|
||||
IntPtr tu = Marshal.AllocHGlobal( bufLength );
|
||||
int cb = bufLength;
|
||||
if (NamedPipeNative.GetTokenInformation( token, NamedPipeNative.TOKEN_INFORMATION_CLASS.TokenUser, tu, cb, ref cb ))
|
||||
Console.WriteLine("GetTokenInformation successful");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("GetTokenInformation NOT successful");
|
||||
uint error = NamedPipeNative.GetLastError();
|
||||
Console.WriteLine("error" + error.ToString());
|
||||
}
|
||||
|
||||
tokUser = (NamedPipeNative.TOKEN_USER) Marshal.PtrToStructure(tu, typeof(NamedPipeNative.TOKEN_USER) );
|
||||
//sb.Append(DumpAccountSid(tokUser.User.Sid));
|
||||
IntPtr pUserID = tokUser.User.Sid;
|
||||
//Console.WriteLine("UserID: " + pUserID);
|
||||
|
||||
DumpAccountSid(pUserID);
|
||||
Marshal.FreeHGlobal( tu );
|
||||
|
||||
|
||||
tu = Marshal.AllocHGlobal(bufLength);
|
||||
cb = bufLength;
|
||||
|
||||
// get token states
|
||||
NamedPipeNative.TOKEN_STATISTICS stats;
|
||||
|
||||
if (NamedPipeNative.GetTokenInformation(token, NamedPipeNative.TOKEN_INFORMATION_CLASS.TokenStatistics, tu, cb, ref cb))
|
||||
{
|
||||
stats = (NamedPipeNative.TOKEN_STATISTICS) Marshal.PtrToStructure(tu, typeof(NamedPipeNative.TOKEN_STATISTICS));
|
||||
Console.WriteLine("UserLow: "+stats.AuthenticationId.LowPart.ToString());
|
||||
Console.WriteLine("UserHigh: "+stats.AuthenticationId.HighPart.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("failed");
|
||||
}
|
||||
|
||||
return (int)pUserID;
|
||||
}
|
||||
|
||||
|
||||
static string DumpAccountSid(IntPtr SID)
|
||||
{
|
||||
int cchAccount = 0;
|
||||
int cchDomain = 0;
|
||||
int snu = 0 ;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Caller allocated buffer
|
||||
StringBuilder Account= null;
|
||||
StringBuilder Domain = null;
|
||||
bool ret = NamedPipeNative.LookupAccountSid(null, SID, Account, ref cchAccount, Domain, ref cchDomain, ref snu);
|
||||
if ( ret == true )
|
||||
if ( Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS )
|
||||
return "Error";
|
||||
try
|
||||
{
|
||||
Account = new StringBuilder( cchAccount );
|
||||
Domain = new StringBuilder( cchDomain );
|
||||
ret = NamedPipeNative.LookupAccountSid(null, SID, Account, ref cchAccount, Domain, ref cchDomain, ref snu);
|
||||
if (ret)
|
||||
{
|
||||
sb.Append(Domain);
|
||||
sb.Append(@"\\");
|
||||
sb.Append(Account);
|
||||
}
|
||||
else
|
||||
Console.WriteLine("logon account (no name) ");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
string SidString = null;
|
||||
NamedPipeNative.ConvertSidToStringSid(SID, ref SidString);
|
||||
sb.Append("\nSID: ");
|
||||
sb.Append(SidString);
|
||||
|
||||
|
||||
Console.WriteLine("Acct info: "+ sb.ToString());
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static int GetLocalUserID(PipeHandle handle, ref int lowPart, ref int highPart, ref string SidString)
|
||||
{
|
||||
int rcode = -1;
|
||||
// get client userID
|
||||
int code = NamedPipeNative.ImpersonateNamedPipeClient(handle.Handle);
|
||||
if (code == 0)
|
||||
{
|
||||
uint lastError = NamedPipeNative.GetLastError();
|
||||
Console.WriteLine("ImpersonateNamedPipeClient Error: "+rcode.ToString());
|
||||
return -1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IntPtr hThread = NamedPipeNative.GetCurrentThread();
|
||||
uint iDesiredInfo = 24; //TOKEN_QUERY | TOKEN_QUERY_SOURCE;
|
||||
IntPtr userToken = Marshal.AllocHGlobal(4);
|
||||
|
||||
if (NamedPipeNative.OpenThreadToken(hThread, iDesiredInfo, true, out userToken))
|
||||
{
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
NamedPipeNative.TOKEN_USER tokUser;
|
||||
const int bufLength = 256;
|
||||
IntPtr tu = Marshal.AllocHGlobal( bufLength );
|
||||
int cb = bufLength;
|
||||
if (NamedPipeNative.GetTokenInformation( userToken, NamedPipeNative.TOKEN_INFORMATION_CLASS.TokenUser, tu, cb, ref cb ))
|
||||
{
|
||||
tokUser = (NamedPipeNative.TOKEN_USER) Marshal.PtrToStructure(tu, typeof(NamedPipeNative.TOKEN_USER) );
|
||||
IntPtr pUserID = tokUser.User.Sid;
|
||||
Marshal.FreeHGlobal( tu );
|
||||
|
||||
// get SID
|
||||
//string SidString = null;
|
||||
NamedPipeNative.ConvertSidToStringSid(pUserID, ref SidString);
|
||||
|
||||
// get token states
|
||||
tu = Marshal.AllocHGlobal(bufLength);
|
||||
cb = bufLength;
|
||||
NamedPipeNative.TOKEN_STATISTICS stats;
|
||||
if (NamedPipeNative.GetTokenInformation(userToken, NamedPipeNative.TOKEN_INFORMATION_CLASS.TokenStatistics, tu, cb, ref cb))
|
||||
{
|
||||
stats = (NamedPipeNative.TOKEN_STATISTICS) Marshal.PtrToStructure(tu, typeof(NamedPipeNative.TOKEN_STATISTICS));
|
||||
// copy low and high part
|
||||
lowPart = stats.AuthenticationId.LowPart;
|
||||
highPart = stats.AuthenticationId.HighPart;
|
||||
rcode = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("GetTokenInformation NOT successful");
|
||||
uint error = NamedPipeNative.GetLastError();
|
||||
Console.WriteLine("error" + error.ToString());
|
||||
}
|
||||
|
||||
// close handle
|
||||
NamedPipeNative.CloseHandle(hThread);
|
||||
NamedPipeNative.RevertToSelf();
|
||||
}
|
||||
else
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
uint errorcode = NamedPipeNative.GetLastError();
|
||||
Console.WriteLine("OpenThreadToken Error: "+ errorcode.ToString() + " code2: "+rcode.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
Console.WriteLine(ex.ToString());
|
||||
return rcode;
|
||||
}
|
||||
// end
|
||||
|
||||
return rcode;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Holds the operating system native handle and the current state of the pipe connection.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public sealed class PipeHandle {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The operating system native handle.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public IntPtr Handle;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// The current state of the pipe connection.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public InterProcessConnectionState State;
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a PipeHandle instance using the passed native handle.
|
||||
/// </summary>
|
||||
/// <param name="hnd">The native handle.</param>
|
||||
#endregion
|
||||
public PipeHandle (int hnd) {
|
||||
this.Handle = new IntPtr(hnd);
|
||||
this.State = InterProcessConnectionState.NotSet;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a PipeHandle instance using the provided native handle and state.
|
||||
/// </summary>
|
||||
/// <param name="hnd">The native handle.</param>
|
||||
/// <param name="state">The state of the pipe connection.</param>
|
||||
#endregion
|
||||
public PipeHandle (int hnd, InterProcessConnectionState state) {
|
||||
this.Handle = new IntPtr(hnd);
|
||||
this.State = state;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a PipeHandle instance with an invalid native handle.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public PipeHandle () {
|
||||
this.Handle = new IntPtr(NamedPipeNative.INVALID_HANDLE_VALUE);
|
||||
this.State = InterProcessConnectionState.NotSet;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.IO;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
using sscs.communication.win.NamedPipes;
|
||||
|
||||
namespace sscs.communication.win {
|
||||
|
||||
public class PipeManager : IChannelManager {
|
||||
|
||||
public Hashtable Pipes;
|
||||
|
||||
private uint NumberPipes = 5;
|
||||
private uint OutBuffer = 65536; //512;
|
||||
private uint InBuffer = 65536; //512;
|
||||
private const int MAX_READ_BYTES = 5000;
|
||||
private bool _listen = true;
|
||||
public bool Listen {
|
||||
get {
|
||||
return _listen;
|
||||
}
|
||||
set {
|
||||
_listen=value;
|
||||
}
|
||||
}
|
||||
private int numChannels = 0;
|
||||
private Hashtable _pipes = new Hashtable();
|
||||
//private Thread MainThread;
|
||||
//private string PipeName = XTIER_RPC_PIPE;
|
||||
private string XTIER_RPC_PIPE = "\\\\.\\PIPE\\SS_RPC_PIPE";
|
||||
private ManualResetEvent Mre;
|
||||
private const int PIPE_MAX_STUFFED_TIME = 5000;
|
||||
|
||||
public object SyncRoot = new object();
|
||||
|
||||
public void Initialize() {
|
||||
Pipes = Hashtable.Synchronized(_pipes);
|
||||
Mre = new ManualResetEvent(false);
|
||||
/*
|
||||
MainThread = new Thread(new ThreadStart(Start));
|
||||
MainThread.IsBackground = true;
|
||||
MainThread.Name = "Main Pipe Thread";
|
||||
MainThread.Start();
|
||||
*/
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
public string HandleRequest(string request) {
|
||||
string returnVal;
|
||||
|
||||
//Form1.ActivityRef.AppendText(request + Environment.NewLine);
|
||||
returnVal = "Response to: " + request;
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
try {
|
||||
while (_listen) {
|
||||
int[] keys = new int[Pipes.Keys.Count];
|
||||
Pipes.Keys.CopyTo(keys,0);
|
||||
foreach (int key in keys) {
|
||||
ServerNamedPipe serverPipe = (ServerNamedPipe)Pipes[key];
|
||||
if (serverPipe != null && DateTime.Now.Subtract(serverPipe.LastAction).Milliseconds > PIPE_MAX_STUFFED_TIME && serverPipe.PipeConnection.GetState() != InterProcessConnectionState.WaitingForClient) {
|
||||
serverPipe.Listen = false;
|
||||
serverPipe.PipeThread.Abort();
|
||||
RemoveServerChannel(serverPipe.PipeConnection.NativeHandle);
|
||||
}
|
||||
}
|
||||
if (numChannels <= NumberPipes) {
|
||||
ServerNamedPipe pipe = new ServerNamedPipe(XTIER_RPC_PIPE, OutBuffer, InBuffer, MAX_READ_BYTES);
|
||||
try {
|
||||
pipe.Connect();
|
||||
pipe.LastAction = DateTime.Now;
|
||||
System.Threading.Interlocked.Increment(ref numChannels);
|
||||
pipe.Start();
|
||||
Pipes.Add(pipe.PipeConnection.NativeHandle, pipe);
|
||||
}
|
||||
catch (InterProcessIOException) {
|
||||
RemoveServerChannel(pipe.PipeConnection.NativeHandle);
|
||||
pipe.Dispose();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mre.Reset();
|
||||
Mre.WaitOne(1000, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception starting server: "+e.ToString());
|
||||
// Log exception
|
||||
}
|
||||
}
|
||||
public void Stop() {
|
||||
_listen = false;
|
||||
Mre.Set();
|
||||
try {
|
||||
int[] keys = new int[Pipes.Keys.Count];
|
||||
Pipes.Keys.CopyTo(keys,0);
|
||||
foreach (int key in keys) {
|
||||
((ServerNamedPipe)Pipes[key]).Listen = false;
|
||||
}
|
||||
int i = numChannels * 3;
|
||||
for (int j = 0; j < i; j++) {
|
||||
StopServerPipe();
|
||||
}
|
||||
Pipes.Clear();
|
||||
Mre.Close();
|
||||
Mre = null;
|
||||
}
|
||||
catch {
|
||||
// Log exception
|
||||
}
|
||||
}
|
||||
|
||||
public void WakeUp() {
|
||||
if (Mre != null) {
|
||||
Mre.Set();
|
||||
}
|
||||
}
|
||||
private void StopServerPipe() {
|
||||
try {
|
||||
ClientPipeConnection pipe = new ClientPipeConnection(XTIER_RPC_PIPE);
|
||||
if (pipe.TryConnect()) {
|
||||
pipe.Close();
|
||||
}
|
||||
} catch {
|
||||
// Log exception
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveServerChannel(object param) {
|
||||
int handle = (int)param;
|
||||
System.Threading.Interlocked.Decrement(ref numChannels);
|
||||
Pipes.Remove(handle);
|
||||
this.WakeUp();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
using sscs.communication.win.NamedPipes;
|
||||
|
||||
namespace sscs.communication.win {
|
||||
|
||||
public sealed class ServerNamedPipe : IDisposable {
|
||||
internal Thread PipeThread;
|
||||
internal ServerPipeConnection PipeConnection;
|
||||
internal bool Listen = true;
|
||||
internal DateTime LastAction;
|
||||
private bool disposed = false;
|
||||
|
||||
private void PipeListener() {
|
||||
CheckIfDisposed();
|
||||
try {
|
||||
Listen = true;
|
||||
while (Listen) {
|
||||
LastAction = DateTime.Now;
|
||||
|
||||
// Service Client (new code)
|
||||
IPCChannel ipcChannel = IPCChannel.Create(PipeConnection);
|
||||
AppHandler appHandler = new AppHandler(ipcChannel);
|
||||
|
||||
try
|
||||
{
|
||||
int retVal = appHandler.ServiceApp();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
ipcChannel.Close();
|
||||
}
|
||||
|
||||
LastAction = DateTime.Now;
|
||||
PipeConnection.Disconnect();
|
||||
if (Listen) {
|
||||
Connect();
|
||||
}
|
||||
WinCommunication.PipeManager.WakeUp();
|
||||
}
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException) { }
|
||||
catch (System.Threading.ThreadStateException) { }
|
||||
catch (Exception) {
|
||||
// Log exception
|
||||
|
||||
}
|
||||
finally {
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
internal void Connect() {
|
||||
CheckIfDisposed();
|
||||
PipeConnection.Connect();
|
||||
}
|
||||
internal void Close() {
|
||||
CheckIfDisposed();
|
||||
this.Listen = false;
|
||||
WinCommunication.PipeManager.RemoveServerChannel(this.PipeConnection.NativeHandle);
|
||||
this.Dispose();
|
||||
}
|
||||
internal void Start() {
|
||||
CheckIfDisposed();
|
||||
PipeThread.Start();
|
||||
}
|
||||
private void CheckIfDisposed() {
|
||||
if(this.disposed) {
|
||||
throw new ObjectDisposedException("ServerNamedPipe");
|
||||
}
|
||||
}
|
||||
public void Dispose() {
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
private void Dispose(bool disposing) {
|
||||
if(!this.disposed) {
|
||||
PipeConnection.Dispose();
|
||||
if (PipeThread != null) {
|
||||
try {
|
||||
PipeThread.Abort();
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException) { }
|
||||
catch (System.Threading.ThreadStateException) { }
|
||||
catch (Exception) {
|
||||
// Log exception
|
||||
}
|
||||
}
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
~ServerNamedPipe() {
|
||||
Dispose(false);
|
||||
}
|
||||
internal ServerNamedPipe(string name, uint outBuffer, uint inBuffer, int maxReadBytes) {
|
||||
PipeConnection = new ServerPipeConnection(name, outBuffer, inBuffer, maxReadBytes);
|
||||
PipeThread = new Thread(new ThreadStart(PipeListener));
|
||||
PipeThread.IsBackground = true;
|
||||
PipeThread.Name = "Pipe Thread " + this.PipeConnection.NativeHandle.ToString();
|
||||
LastAction = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// Created by Ivan Latunov - IvanWeb.com //
|
||||
//----------------------------------------------//
|
||||
// This program is free software. You can //
|
||||
// redistribute it and/or modify it as you wish //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using sscs.communication.win.InterProcessComm;
|
||||
|
||||
namespace sscs.communication.win.NamedPipes {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Used by server applications to communicate with client ones by using named pipes.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public sealed class ServerPipeConnection : APipeConnection {
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Disconnects a client named pipe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When a client named pipe is disconnected, the server one is not closed.
|
||||
/// The latter can later be reused by starting to listen again.<br/><br/>
|
||||
/// In a message oriented protocol the server will disconnect the client when the
|
||||
/// response is sent and all the data is flushed. The same server named pipe
|
||||
/// could then be reused by calling the
|
||||
/// <see cref="AppModule.NamedPipes.ServerPipeConnection.Connect">Connect</see> method.
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public void Disconnect() {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.Disconnect(this.Handle);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Closes the operating system native handle of the named pipe.
|
||||
/// </summary>
|
||||
#endregion
|
||||
public override void Close() {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.Close(this.Handle);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Starts listening to client pipe connections.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will block the program execution until a client pipe attempts
|
||||
/// to establish a connection.<br/><br/>
|
||||
/// When a client named pipe is disconnected, the server one is not closed.
|
||||
/// The latter can later be reused by starting to listen again.<br/><br/>
|
||||
/// </remarks>
|
||||
#endregion
|
||||
public override void Connect() {
|
||||
CheckIfDisposed();
|
||||
NamedPipeWrapper.Connect(this.Handle);
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Creates a ServerPipeConnection instance and the underlying operating system handle.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the pipe.</param>
|
||||
/// <param name="outBuffer">The outbound buffer.</param>
|
||||
/// <param name="inBuffer">The inbound buffer.</param>
|
||||
/// <param name="maxReadBytes">The maximum bytes to read from clients.</param>
|
||||
#endregion
|
||||
public ServerPipeConnection(string name, uint outBuffer, uint inBuffer, int maxReadBytes) {
|
||||
this.Name = name;
|
||||
this.Handle = NamedPipeWrapper.Create(name, outBuffer, inBuffer);
|
||||
this.maxReadBytes = maxReadBytes;
|
||||
}
|
||||
#region Comments
|
||||
/// <summary>
|
||||
/// Object destructor.
|
||||
/// </summary>
|
||||
#endregion
|
||||
~ServerPipeConnection() {
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -80,14 +80,14 @@
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "AppModule.NamedPipes"
|
||||
AssemblyName = "AppModule.NamedPipes"
|
||||
HintPath = "..\..\extern\w32\namedpipes\AppModule.NamedPipes.dll"
|
||||
Name = "AppModule.InterProcessComm"
|
||||
Project = "{E98F1F7E-40B6-44C8-AC66-EC867B141FA1}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
<Reference
|
||||
Name = "AppModule.InterProcessComm"
|
||||
AssemblyName = "AppModule.InterProcessComm"
|
||||
HintPath = "..\..\extern\w32\namedpipes\AppModule.InterProcessComm.dll"
|
||||
Name = "AppModule.NamedPipes"
|
||||
Project = "{077B53BB-404A-4B2F-BA17-AAE98C5E9C66}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP LastOpenVersion = "7.10.3077" >
|
||||
<Build>
|
||||
<Settings ReferencePath = "D:\csharp\namedpipe2\AppModule.InterProcessComm\bin\Debug\;D:\csharp\namedpipe2\AppModule.NamedPipes\bin\Debug\;D:\casatest\extern\w32\namedpipes\;D:\casaoutside\extern\w32\namedpipes\" >
|
||||
<Settings ReferencePath = "D:\csharp\namedpipe2\AppModule.InterProcessComm\bin\Debug\;D:\csharp\namedpipe2\AppModule.NamedPipes\bin\Debug\;D:\casatest\extern\w32\namedpipes\;D:\casaoutside\extern\w32\namedpipes\;D:\casaAll\trunk\extern\w32\namedpipes\" >
|
||||
<Config
|
||||
Name = "Debug"
|
||||
EnableASPDebugging = "false"
|
||||
|
@ -9,8 +9,8 @@ namespace Novell.CASA.MiCasa.Common
|
||||
[Serializable]
|
||||
public class LinkedKeyInfo
|
||||
{
|
||||
private string m_sDestStoreID = null;
|
||||
private string m_sDestKeychainID = null;
|
||||
//private string m_sDestStoreID = null;
|
||||
//private string m_sDestKeychainID = null;
|
||||
private string m_sDestSecretID = null;
|
||||
private string m_sDestKeyID = null;
|
||||
|
||||
|
@ -119,6 +119,16 @@
|
||||
Project = "{57CD94A2-5B4A-40C3-8189-CB760FB78357}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
<Reference
|
||||
Name = "AppModule.InterProcessComm"
|
||||
Project = "{E98F1F7E-40B6-44C8-AC66-EC867B141FA1}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
<Reference
|
||||
Name = "AppModule.NamedPipes"
|
||||
Project = "{077B53BB-404A-4B2F-BA17-AAE98C5E9C66}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
@ -229,72 +239,12 @@
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\InterProcessComm\IChannelManager.cs"
|
||||
RelPath = "communication\win\PipeManager.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\InterProcessComm\IClientChannel.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\InterProcessComm\IInterProcessConnection.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\InterProcessComm\InterProcessConnectionState.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\InterProcessComm\InterProcessIOException.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\APipeConnection.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\ClientPipeConnection.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\NamedPipeIOException.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\NamedPipeNative.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\NamedPipeWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\PipeHandle.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\PipeManager.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\ServerNamedPipe.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "communication\win\NamedPipes\ServerPipeConnection.cs"
|
||||
RelPath = "communication\win\ServerNamedPipe.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user