inital
This commit is contained in:
290
FasdDesktopUi/Basics/NamedPipes.cs
Normal file
290
FasdDesktopUi/Basics/NamedPipes.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
using System.IO.Pipes;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using C4IT.Logging;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
static public class cF4sdPipeClient
|
||||
{
|
||||
static public bool Send(string SendStr, string PipeName, int TimeOut = 1000)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
if (DefaultLogger.IsDebug)
|
||||
{
|
||||
var _msg = new List<string>() { $"send to pipe {PipeName}", SendStr };
|
||||
DefaultLogger.LogList(LogLevels.Debug, _msg);
|
||||
}
|
||||
|
||||
NamedPipeClientStream pipeStream = new NamedPipeClientStream
|
||||
(".", PipeName, PipeDirection.Out, PipeOptions.WriteThrough);
|
||||
|
||||
// The connect function will indefinitely wait for the pipe to become available
|
||||
// If that is not acceptable specify a maximum waiting time (in ms)
|
||||
pipeStream.Connect(TimeOut);
|
||||
|
||||
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
|
||||
pipeStream.Write(_buffer, 0, _buffer.Length);
|
||||
pipeStream.Flush();
|
||||
pipeStream.Close();
|
||||
pipeStream.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (TimeoutException oEX)
|
||||
{
|
||||
if (cLogManager.DefaultLogger.IsDebug)
|
||||
cLogManager.DefaultLogger.LogException(oEX);
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public void RegisterProtocol(string protocolString, string urlCommand)
|
||||
{
|
||||
try
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
var u = new Uri(codeBase);
|
||||
var Path = u.LocalPath;
|
||||
var RegBase = Registry.CurrentUser.OpenSubKey("Software\\Classes", true);
|
||||
var RegHandler = RegBase.CreateSubKey(protocolString.ToUpperInvariant());
|
||||
RegHandler.SetValue("", $"URL: {protocolString.ToUpperInvariant()} Protocol Handler");
|
||||
RegHandler.SetValue("URL Protocol", "");
|
||||
var RegHandler2 = RegHandler.CreateSubKey("DefaultIcon");
|
||||
RegHandler2.SetValue("", Path);
|
||||
var RegHandler3 = RegHandler.CreateSubKey("shell\\open\\command");
|
||||
RegHandler3.SetValue("", $"\"{Path}\" {urlCommand.ToLowerInvariant()} \"%1\"");
|
||||
|
||||
RegHandler = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Internet Explorer\\ProtocolExecute\\{protocolString.ToLowerInvariant()}");
|
||||
RegHandler.SetValue("WarnOnOpen", 0,RegistryValueKind.DWord);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void DelegateMessage(string Reply);
|
||||
|
||||
public class cF4sdPipeServer : IDisposable
|
||||
{
|
||||
public event DelegateMessage PipeMessage;
|
||||
string _pipeName;
|
||||
NamedPipeServerStream pipeServer;
|
||||
bool _LowerIntegrity;
|
||||
int _MaxSize;
|
||||
|
||||
public void Listen(string PipeName, int MaxSize = 255, bool LowerIntegrity = false, int Timeout = 10000)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Set to class level var so we can re-use in the async callback method
|
||||
_pipeName = PipeName;
|
||||
_MaxSize = MaxSize;
|
||||
_LowerIntegrity = LowerIntegrity;
|
||||
|
||||
if (pipeServer != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
pipeServer.Close();
|
||||
pipeServer.Dispose();
|
||||
pipeServer = null;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
bool _connected = false;
|
||||
bool _firstTry = true;
|
||||
var _startTime = DateTime.UtcNow;
|
||||
while ((DateTime.UtcNow - _startTime).TotalMilliseconds < Timeout && !_connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_firstTry)
|
||||
Thread.Sleep(200);
|
||||
_firstTry = false;
|
||||
|
||||
// Create the new async pipe
|
||||
if (pipeServer == null)
|
||||
pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
if (_LowerIntegrity)
|
||||
InterProcessSecurity.SetLowIntegrityLevel(pipeServer.SafePipeHandle);
|
||||
|
||||
// Wait for a connection
|
||||
var _res = pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
|
||||
_connected = _res != null;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
if (!_connected)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogEntry(LogLevels.Error, $"The pipe '{PipeName}' could not be opened in listen mode.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception oEX)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(oEX);
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitForConnectionCallBack(IAsyncResult iar)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the pipe
|
||||
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
|
||||
// End waiting for the connection
|
||||
pipeServer.EndWaitForConnection(iar);
|
||||
|
||||
byte[] buffer = new byte[_MaxSize];
|
||||
|
||||
// Read the incoming message
|
||||
int count = pipeServer.Read(buffer, 0, _MaxSize);
|
||||
|
||||
// Convert byte buffer to string
|
||||
string stringData = Encoding.UTF8.GetString(buffer, 0, count);
|
||||
|
||||
// Pass message back to calling form
|
||||
PipeMessage.Invoke(stringData);
|
||||
|
||||
// Kill original sever and create new wait server
|
||||
pipeServer.Close();
|
||||
pipeServer = null;
|
||||
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,
|
||||
1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
|
||||
if (_LowerIntegrity)
|
||||
InterProcessSecurity.SetLowIntegrityLevel(pipeServer.SafePipeHandle);
|
||||
|
||||
// Recursively wait for the connection again and again....
|
||||
pipeServer.BeginWaitForConnection(
|
||||
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (pipeServer != null)
|
||||
{
|
||||
pipeServer.Close();
|
||||
pipeServer.Dispose();
|
||||
pipeServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static class InterProcessSecurity
|
||||
{
|
||||
|
||||
public const string LOW_INTEGRITY_SSL_SACL = "S:(ML;;NW;;;LW)";
|
||||
|
||||
public static int ERROR_SUCCESS = 0x0;
|
||||
|
||||
public const int LABEL_SECURITY_INFORMATION = 0x00000010;
|
||||
|
||||
public enum SE_OBJECT_TYPE
|
||||
{
|
||||
SE_UNKNOWN_OBJECT_TYPE = 0,
|
||||
SE_FILE_OBJECT,
|
||||
SE_SERVICE,
|
||||
SE_PRINTER,
|
||||
SE_REGISTRY_KEY,
|
||||
SE_LMSHARE,
|
||||
SE_KERNEL_OBJECT,
|
||||
SE_WINDOW_OBJECT,
|
||||
SE_DS_OBJECT,
|
||||
SE_DS_OBJECT_ALL,
|
||||
SE_PROVIDER_DEFINED_OBJECT,
|
||||
SE_WMIGUID_OBJECT,
|
||||
SE_REGISTRY_WOW64_32KEY
|
||||
}
|
||||
|
||||
[DllImport("advapi32.dll", EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern Boolean ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String strSecurityDescriptor,
|
||||
UInt32 sDRevision,
|
||||
ref IntPtr securityDescriptor,
|
||||
ref UInt32 securityDescriptorSize);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "LocalFree")]
|
||||
public static extern UInt32 LocalFree(IntPtr hMem);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "SetSecurityInfo")]
|
||||
public static extern int SetSecurityInfo(SafeHandle hFileMappingObject,
|
||||
SE_OBJECT_TYPE objectType,
|
||||
Int32 securityInfo,
|
||||
IntPtr psidOwner,
|
||||
IntPtr psidGroup,
|
||||
IntPtr pDacl,
|
||||
IntPtr pSacl);
|
||||
[DllImport("advapi32.dll", EntryPoint = "GetSecurityDescriptorSacl")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern Boolean GetSecurityDescriptorSacl(
|
||||
IntPtr pSecurityDescriptor,
|
||||
out IntPtr lpbSaclPresent,
|
||||
out IntPtr pSacl,
|
||||
out IntPtr lpbSaclDefaulted);
|
||||
|
||||
public static void SetLowIntegrityLevel(SafeHandle hObject)
|
||||
{
|
||||
IntPtr pSD = IntPtr.Zero;
|
||||
uint securityDescriptorSize = 0;
|
||||
|
||||
if (ConvertStringSecurityDescriptorToSecurityDescriptor(LOW_INTEGRITY_SSL_SACL, 1, ref pSD, ref securityDescriptorSize))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GetSecurityDescriptorSacl(pSD, out IntPtr lpbSaclPresent, out IntPtr pSacl, out IntPtr lpbSaclDefaulted))
|
||||
{
|
||||
var err = SetSecurityInfo(hObject,
|
||||
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
|
||||
LABEL_SECURITY_INFORMATION,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
pSacl);
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
LocalFree(pSD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user