mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Rewrote Overwatch datareader to use a named pipe
This commit is contained in:
parent
20eca5e849
commit
f8c35df098
@ -38,8 +38,8 @@
|
||||
<SupportUrl>https://github.com/SpoinkyNL/Artemis/wiki/Frequently-Asked-Questions-%28FAQ%29</SupportUrl>
|
||||
<ProductName>Artemis</ProductName>
|
||||
<PublisherName>Artemis</PublisherName>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.2.0.0</ApplicationVersion>
|
||||
<ApplicationRevision>1</ApplicationRevision>
|
||||
<ApplicationVersion>1.2.0.1</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<CreateDesktopShortcut>true</CreateDesktopShortcut>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
@ -471,7 +471,7 @@
|
||||
<Compile Include="Utilities\ColorHelpers.cs" />
|
||||
<Compile Include="Utilities\Converters\JsonConverters.cs" />
|
||||
<Compile Include="Utilities\Converters\ValueConverters.cs" />
|
||||
<Compile Include="Utilities\DataReaders\MmfReader.cs" />
|
||||
<Compile Include="Utilities\DataReaders\DllManager.cs" />
|
||||
<Compile Include="Utilities\ExtensionMethods.cs" />
|
||||
<Compile Include="Utilities\GameState\GameDataReceivedEventArgs.cs" />
|
||||
<Compile Include="Utilities\GameState\GameStateWebServer.cs" />
|
||||
@ -480,9 +480,7 @@
|
||||
<Compile Include="Utilities\ImageUtilities.cs" />
|
||||
<Compile Include="Utilities\Keyboard\KeyboardHook.cs" />
|
||||
<Compile Include="Utilities\Logging.cs" />
|
||||
<Compile Include="Utilities\LogitechDll\DllManager.cs" />
|
||||
<Compile Include="Utilities\LogitechDll\NamedPipeServer.cs" />
|
||||
<Compile Include="Utilities\LogitechDll\PipeServer.cs" />
|
||||
<Compile Include="Utilities\DataReaders\PipeServer.cs" />
|
||||
<Compile Include="Utilities\Memory\GamePointer.cs" />
|
||||
<Compile Include="Utilities\Memory\Memory.cs" />
|
||||
<Compile Include="Utilities\Memory\MemoryHelpers.cs" />
|
||||
|
||||
@ -3,7 +3,7 @@ using System.Threading;
|
||||
using System.Windows;
|
||||
using Artemis.DeviceProviders.Logitech.Utilities;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.LogitechDll;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Artemis.DeviceProviders.Logitech
|
||||
@ -24,7 +24,7 @@ namespace Artemis.DeviceProviders.Logitech
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DllManager.RestoreDll())
|
||||
if (DllManager.RestoreLogitechDll())
|
||||
RestoreDll();
|
||||
int majorNum = 0, minorNum = 0, buildNum = 0;
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ using System.Timers;
|
||||
using Artemis.Events;
|
||||
using Artemis.Models;
|
||||
using Artemis.Modules.Effects.ProfilePreview;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
using Artemis.Utilities.GameState;
|
||||
using Artemis.Utilities.Keyboard;
|
||||
using Artemis.Utilities.LogitechDll;
|
||||
using Artemis.ViewModels;
|
||||
using Caliburn.Micro;
|
||||
using Ninject;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Events;
|
||||
using Artemis.Managers;
|
||||
@ -8,7 +9,6 @@ using Artemis.Models;
|
||||
using Artemis.Models.Interfaces;
|
||||
using Artemis.Profiles.Layers.Models;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
using Caliburn.Micro;
|
||||
|
||||
namespace Artemis.Modules.Games.Overwatch
|
||||
@ -17,6 +17,7 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
{
|
||||
private readonly IEventAggregator _events;
|
||||
private DateTime _characterChange;
|
||||
private string _lastMessage;
|
||||
// Using sticky values on these since they can cause flickering
|
||||
private StickyValue<OverwatchStatus> _stickyStatus;
|
||||
private StickyValue<bool> _stickyUltimateReady;
|
||||
@ -34,7 +35,6 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
Enabled = Settings.Enabled;
|
||||
Initialized = false;
|
||||
|
||||
MmfReader = new MmfReader("overwatchMmf", MainManager.Logger);
|
||||
LoadOverwatchCharacters();
|
||||
}
|
||||
|
||||
@ -45,8 +45,6 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
|
||||
public List<CharacterColor> OverwatchCharacters { get; set; }
|
||||
|
||||
public MmfReader MmfReader { get; set; }
|
||||
|
||||
public int Scale { get; set; }
|
||||
|
||||
private void LoadOverwatchCharacters()
|
||||
@ -82,15 +80,27 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
_stickyStatus = new StickyValue<OverwatchStatus>(300);
|
||||
_stickyUltimateReady = new StickyValue<bool>(350);
|
||||
_stickyUltimateUsed = new StickyValue<bool>(350);
|
||||
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
|
||||
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Initialized = false;
|
||||
|
||||
_stickyStatus.Dispose();
|
||||
_stickyUltimateReady.Dispose();
|
||||
_stickyUltimateUsed.Dispose();
|
||||
Initialized = false;
|
||||
|
||||
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
|
||||
}
|
||||
|
||||
private void PipeServerOnPipeMessage(string message)
|
||||
{
|
||||
|
||||
_lastMessage = message;
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
@ -110,7 +120,12 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
public void UpdateOverwatch()
|
||||
{
|
||||
var gameDataModel = (OverwatchDataModel) DataModel;
|
||||
var colors = MmfReader.GetColorArray();
|
||||
|
||||
if (_lastMessage == null)
|
||||
return;
|
||||
|
||||
var colors = ParseColorArray(_lastMessage);
|
||||
|
||||
if (colors == null)
|
||||
return;
|
||||
|
||||
@ -135,6 +150,41 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
ParseAbilities(gameDataModel, colors);
|
||||
}
|
||||
|
||||
public Color[,] ParseColorArray(string arrayString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arrayString))
|
||||
return null;
|
||||
var intermediateArray = arrayString.Split('|');
|
||||
if (intermediateArray[0] == "1" || intermediateArray.Length < 2)
|
||||
return null;
|
||||
var array = intermediateArray[1].Substring(1).Split(' ');
|
||||
if (!array.Any())
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
var colors = new Color[6, 22];
|
||||
foreach (var intermediate in array)
|
||||
{
|
||||
if (intermediate.Length > 16)
|
||||
continue;
|
||||
|
||||
// Can't parse to a byte directly since it may contain values >254
|
||||
var parts = intermediate.Split(',').Select(int.Parse).ToArray();
|
||||
if (parts[0] >= 5 && parts[1] >= 21)
|
||||
continue;
|
||||
|
||||
colors[parts[0], parts[1]] = Color.FromRgb((byte) parts[2], (byte) parts[3], (byte) parts[4]);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
MainManager.Logger.Trace(e, "Failed to parse to color array");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseGameSate(OverwatchDataModel gameDataModel, Color[,] colors)
|
||||
{
|
||||
if (_ultimateUsed.AddSeconds(5) >= DateTime.Now)
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Artemis.InjectionFactories;
|
||||
using Artemis.Managers;
|
||||
using Artemis.Properties;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
using Artemis.ViewModels.Abstract;
|
||||
using Caliburn.Micro;
|
||||
using Microsoft.Win32;
|
||||
@ -72,14 +71,7 @@ namespace Artemis.Modules.Games.Overwatch
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(path + @"\RzChromaSDK64.dll", Resources.RzChromaSDK64);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger?.Error(e, "Couldn't place Overwatch DLL, Overwatch support won't work.");
|
||||
}
|
||||
DllManager.PlaceRazerDll(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ using Artemis.Managers;
|
||||
using Artemis.Models;
|
||||
using Artemis.Profiles.Layers.Models;
|
||||
using Artemis.Utilities;
|
||||
using Artemis.Utilities.LogitechDll;
|
||||
using Artemis.Utilities.DataReaders;
|
||||
|
||||
namespace Artemis.Modules.Games.TheDivision
|
||||
{
|
||||
@ -34,11 +34,13 @@ namespace Artemis.Modules.Games.TheDivision
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
Thread.Sleep(2000);
|
||||
DllManager.RestoreDll();
|
||||
DllManager.RestoreLogitechDll();
|
||||
});
|
||||
|
||||
_stickyAmmo.Dispose();
|
||||
_stickyHp.Dispose();
|
||||
|
||||
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
@ -48,7 +50,7 @@ namespace Artemis.Modules.Games.TheDivision
|
||||
_stickyAmmo = new StickyValue<bool>(200);
|
||||
_stickyHp = new StickyValue<bool>(200);
|
||||
|
||||
DllManager.PlaceDll();
|
||||
DllManager.PlaceLogitechDll();
|
||||
|
||||
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
|
||||
Initialized = true;
|
||||
|
||||
Binary file not shown.
@ -1,91 +1,116 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Artemis.Properties;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Artemis.Utilities.LogitechDll
|
||||
{
|
||||
internal static class DllManager
|
||||
{
|
||||
private const string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\";
|
||||
|
||||
public static bool RestoreDll()
|
||||
{
|
||||
if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt"))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// Get rid of our own DLL
|
||||
File.Delete(LogitechPath + @"\LogitechLed.dll");
|
||||
|
||||
// Restore the backup
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
|
||||
File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll");
|
||||
|
||||
File.Delete(LogitechPath + @"\artemis.txt");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlaceDll()
|
||||
{
|
||||
if (DllPlaced())
|
||||
return;
|
||||
|
||||
// Create directory structure, just in case
|
||||
Directory.CreateDirectory(LogitechPath + @"");
|
||||
|
||||
// Backup the existing DLL
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll"))
|
||||
{
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
|
||||
File.Delete(LogitechPath + @"\LogitechLed.dll.bak");
|
||||
File.Move(LogitechPath + @"\LogitechLed.dll", LogitechPath + @"\LogitechLed.dll.bak");
|
||||
}
|
||||
|
||||
// Copy our own DLL in place
|
||||
File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll",
|
||||
Resources.LogitechLED);
|
||||
|
||||
// A token to show the file is placed
|
||||
File.Create(LogitechPath + @"\artemis.txt");
|
||||
|
||||
// If the user doesn't have a Logitech device, the CLSID will be missing
|
||||
// and we should create it ourselves.
|
||||
if (!RegistryKeyPlaced())
|
||||
PlaceRegistryKey();
|
||||
}
|
||||
|
||||
public static bool DllPlaced()
|
||||
{
|
||||
if (!Directory.Exists(LogitechPath + @""))
|
||||
return false;
|
||||
if (!RegistryKeyPlaced())
|
||||
return false;
|
||||
|
||||
return File.Exists(LogitechPath + @"\artemis.txt");
|
||||
}
|
||||
|
||||
private static bool RegistryKeyPlaced()
|
||||
{
|
||||
var key = Registry
|
||||
.LocalMachine.OpenSubKey(
|
||||
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary");
|
||||
return key != null;
|
||||
}
|
||||
|
||||
private static void PlaceRegistryKey()
|
||||
{
|
||||
var key = Registry
|
||||
.LocalMachine.OpenSubKey(
|
||||
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
|
||||
key?.SetValue(null, LogitechPath + @"\LogitechLed.dll");
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using Artemis.Modules.Games.Overwatch;
|
||||
using Artemis.Properties;
|
||||
using Microsoft.Win32;
|
||||
using NLog;
|
||||
|
||||
namespace Artemis.Utilities.DataReaders
|
||||
{
|
||||
internal static class DllManager
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
#region Logitech
|
||||
|
||||
private const string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\";
|
||||
|
||||
public static bool RestoreLogitechDll()
|
||||
{
|
||||
if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt"))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// Get rid of our own DLL
|
||||
File.Delete(LogitechPath + @"\LogitechLed.dll");
|
||||
|
||||
// Restore the backup
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
|
||||
File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll");
|
||||
|
||||
File.Delete(LogitechPath + @"\artemis.txt");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlaceLogitechDll()
|
||||
{
|
||||
if (DllPlaced())
|
||||
return;
|
||||
|
||||
// Create directory structure, just in case
|
||||
Directory.CreateDirectory(LogitechPath + @"");
|
||||
|
||||
// Backup the existing DLL
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll"))
|
||||
{
|
||||
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
|
||||
File.Delete(LogitechPath + @"\LogitechLed.dll.bak");
|
||||
File.Move(LogitechPath + @"\LogitechLed.dll", LogitechPath + @"\LogitechLed.dll.bak");
|
||||
}
|
||||
|
||||
// Copy our own DLL in place
|
||||
File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll",
|
||||
Resources.LogitechLED);
|
||||
|
||||
// A token to show the file is placed
|
||||
File.Create(LogitechPath + @"\artemis.txt");
|
||||
|
||||
// If the user doesn't have a Logitech device, the CLSID will be missing
|
||||
// and we should create it ourselves.
|
||||
if (!RegistryKeyPlaced())
|
||||
PlaceRegistryKey();
|
||||
}
|
||||
|
||||
public static bool DllPlaced()
|
||||
{
|
||||
if (!Directory.Exists(LogitechPath + @""))
|
||||
return false;
|
||||
if (!RegistryKeyPlaced())
|
||||
return false;
|
||||
|
||||
return File.Exists(LogitechPath + @"\artemis.txt");
|
||||
}
|
||||
|
||||
private static bool RegistryKeyPlaced()
|
||||
{
|
||||
var key = Registry
|
||||
.LocalMachine.OpenSubKey(
|
||||
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary");
|
||||
return key != null;
|
||||
}
|
||||
|
||||
private static void PlaceRegistryKey()
|
||||
{
|
||||
var key = Registry
|
||||
.LocalMachine.OpenSubKey(
|
||||
@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true);
|
||||
key?.SetValue(null, LogitechPath + @"\LogitechLed.dll");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Razer
|
||||
|
||||
public static void PlaceRazerDll(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(path + @"\RzChromaSDK64.dll", Resources.RzChromaSDK64);
|
||||
Logger.Debug("Successfully placed Razer DLL in {0}", path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, "Couldn't place Razer DLL in {0}", path);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Media;
|
||||
using Ninject.Extensions.Logging;
|
||||
|
||||
namespace Artemis.Utilities.DataReaders
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper class for reading memory managed files
|
||||
/// </summary>
|
||||
public class MmfReader
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MmfReader(string mmfName, ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
MmfName = mmfName;
|
||||
}
|
||||
|
||||
public string MmfName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Turns the MMF into an color array
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Color[,] GetColorArray()
|
||||
{
|
||||
var mffString = ReadMmf(MmfName);
|
||||
if (string.IsNullOrEmpty(mffString))
|
||||
return null;
|
||||
var intermediateArray = mffString.Split('|');
|
||||
if (intermediateArray[0] == "1" || intermediateArray.Length < 2)
|
||||
return null;
|
||||
var array = intermediateArray[1].Substring(1).Split(' ');
|
||||
if (!array.Any())
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
var colors = new Color[6, 22];
|
||||
foreach (var intermediate in array)
|
||||
{
|
||||
if (intermediate.Length > 16)
|
||||
continue;
|
||||
|
||||
// Can't parse to a byte directly since it may contain values >254
|
||||
var parts = intermediate.Split(',').Select(int.Parse).ToArray();
|
||||
if (parts[0] >= 5 && parts[1] >= 21)
|
||||
continue;
|
||||
|
||||
colors[parts[0], parts[1]] = Color.FromRgb((byte) parts[2], (byte) parts[3], (byte) parts[4]);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
_logger.Trace(e, "Failed to parse to color array");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the contents of the given MFF into a string
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
private string ReadMmf(string fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mmf = MemoryMappedFile.OpenExisting(fileName))
|
||||
{
|
||||
using (var stream = mmf.CreateViewStream())
|
||||
{
|
||||
using (var binReader = new BinaryReader(stream))
|
||||
{
|
||||
var allBytes = binReader.ReadBytes((int) stream.Length);
|
||||
return Encoding.UTF8.GetString(allBytes, 0, allBytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
_logger.Trace(e, "Failed to read mff");
|
||||
return null;
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,131 +1,131 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Artemis.Utilities.LogitechDll
|
||||
{
|
||||
// Delegate for passing received message back to caller
|
||||
public delegate void DelegateMessage(string reply);
|
||||
|
||||
public class PipeServer
|
||||
{
|
||||
private string _pipeName;
|
||||
|
||||
public bool Running { get; set; }
|
||||
public event DelegateMessage PipeMessage;
|
||||
|
||||
public void Start(string pipeName)
|
||||
{
|
||||
Running = true;
|
||||
_pipeName = pipeName;
|
||||
var task = new Task(PipeLoop);
|
||||
task.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Running = false;
|
||||
}
|
||||
|
||||
private void PipeLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl,
|
||||
AccessControlType.Allow));
|
||||
|
||||
while (Running)
|
||||
{
|
||||
var namedPipeServerStream = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254,
|
||||
PipeTransmissionMode.Byte, PipeOptions.None, 254, 254, security);
|
||||
|
||||
namedPipeServerStream.WaitForConnection();
|
||||
var buffer = new byte[254];
|
||||
namedPipeServerStream.Read(buffer, 0, 254);
|
||||
namedPipeServerStream.Close();
|
||||
|
||||
var task = new Task(() => HandleMessage(buffer));
|
||||
task.Start();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMessage(byte[] buffer)
|
||||
{
|
||||
var request = Encoding.ASCII.GetString(buffer);
|
||||
PipeMessage?.Invoke(request);
|
||||
}
|
||||
|
||||
public void Listen(string pipeName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
|
||||
|
||||
// Set to class level var so we can re-use in the async callback method
|
||||
_pipeName = pipeName;
|
||||
// Create the new async pipe
|
||||
var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
|
||||
PipeOptions.Asynchronous, 254, 254, security);
|
||||
|
||||
// Wait for a connection
|
||||
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
|
||||
}
|
||||
catch (Exception oEx)
|
||||
{
|
||||
Debug.WriteLine(oEx.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitForConnectionCallBack(IAsyncResult iar)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the pipe
|
||||
var pipeServer = (NamedPipeServerStream) iar.AsyncState;
|
||||
// End waiting for the connection
|
||||
pipeServer.EndWaitForConnection(iar);
|
||||
|
||||
var buffer = new byte[255];
|
||||
|
||||
// Read the incoming message
|
||||
pipeServer.Read(buffer, 0, 255);
|
||||
|
||||
// Convert byte buffer to string
|
||||
var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
|
||||
|
||||
// Pass message back to calling form
|
||||
PipeMessage?.Invoke(stringData);
|
||||
|
||||
// Kill original sever and create new wait server
|
||||
pipeServer.Close();
|
||||
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
|
||||
|
||||
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
|
||||
PipeOptions.Asynchronous, 254, 254, security);
|
||||
|
||||
// Recursively wait for the connection again and again....
|
||||
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Artemis.Utilities.DataReaders
|
||||
{
|
||||
// Delegate for passing received message back to caller
|
||||
public delegate void DelegateMessage(string reply);
|
||||
|
||||
public class PipeServer
|
||||
{
|
||||
private string _pipeName;
|
||||
|
||||
public bool Running { get; set; }
|
||||
public event DelegateMessage PipeMessage;
|
||||
|
||||
public void Start(string pipeName)
|
||||
{
|
||||
Running = true;
|
||||
_pipeName = pipeName;
|
||||
var task = new Task(PipeLoop);
|
||||
task.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Running = false;
|
||||
}
|
||||
|
||||
private void PipeLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl,
|
||||
AccessControlType.Allow));
|
||||
|
||||
while (Running)
|
||||
{
|
||||
var namedPipeServerStream = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254,
|
||||
PipeTransmissionMode.Byte, PipeOptions.None, 4096, 4096, security);
|
||||
|
||||
namedPipeServerStream.WaitForConnection();
|
||||
var buffer = new byte[4096];
|
||||
namedPipeServerStream.Read(buffer, 0, 4096);
|
||||
namedPipeServerStream.Close();
|
||||
|
||||
var task = new Task(() => HandleMessage(buffer));
|
||||
task.Start();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMessage(byte[] buffer)
|
||||
{
|
||||
var request = Encoding.ASCII.GetString(buffer);
|
||||
PipeMessage?.Invoke(request);
|
||||
}
|
||||
|
||||
public void Listen(string pipeName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
|
||||
|
||||
// Set to class level var so we can re-use in the async callback method
|
||||
_pipeName = pipeName;
|
||||
// Create the new async pipe
|
||||
var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
|
||||
PipeOptions.Asynchronous, 254, 254, security);
|
||||
|
||||
// Wait for a connection
|
||||
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
|
||||
}
|
||||
catch (Exception oEx)
|
||||
{
|
||||
Debug.WriteLine(oEx.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitForConnectionCallBack(IAsyncResult iar)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the pipe
|
||||
var pipeServer = (NamedPipeServerStream) iar.AsyncState;
|
||||
// End waiting for the connection
|
||||
pipeServer.EndWaitForConnection(iar);
|
||||
|
||||
var buffer = new byte[255];
|
||||
|
||||
// Read the incoming message
|
||||
pipeServer.Read(buffer, 0, 255);
|
||||
|
||||
// Convert byte buffer to string
|
||||
var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
|
||||
|
||||
// Pass message back to calling form
|
||||
PipeMessage?.Invoke(stringData);
|
||||
|
||||
// Kill original sever and create new wait server
|
||||
pipeServer.Close();
|
||||
|
||||
var security = new PipeSecurity();
|
||||
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
|
||||
|
||||
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
|
||||
PipeOptions.Asynchronous, 254, 254, security);
|
||||
|
||||
// Recursively wait for the connection again and again....
|
||||
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,186 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace Artemis.Utilities.LogitechDll
|
||||
{
|
||||
public class NamedPipeServer
|
||||
{
|
||||
public const uint DUPLEX = 0x00000003;
|
||||
public const uint FILE_FLAG_OVERLAPPED = 0x40000000;
|
||||
|
||||
public const int BUFFER_SIZE = 100;
|
||||
private SafeFileHandle clientHandle;
|
||||
public Client clientse;
|
||||
public int ClientType;
|
||||
private Thread listenThread;
|
||||
|
||||
public string pipeName;
|
||||
|
||||
public NamedPipeServer(string PName, int Mode)
|
||||
{
|
||||
pipeName = PName;
|
||||
ClientType = Mode; //0 Reading Pipe, 1 Writing Pipe
|
||||
}
|
||||
|
||||
public event PipeDataReceivedEventHandler PipeDataReceived;
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern SafeFileHandle CreateNamedPipe(
|
||||
string pipeName,
|
||||
uint dwOpenMode,
|
||||
uint dwPipeMode,
|
||||
uint nMaxInstances,
|
||||
uint nOutBufferSize,
|
||||
uint nInBufferSize,
|
||||
uint nDefaultTimeOut,
|
||||
IntPtr lpSecurityAttributes);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern int ConnectNamedPipe(
|
||||
SafeFileHandle hNamedPipe,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern int DisconnectNamedPipe(
|
||||
SafeFileHandle hNamedPipe);
|
||||
|
||||
public void Start()
|
||||
{
|
||||
listenThread = new Thread(ListenForClients);
|
||||
listenThread.Start();
|
||||
}
|
||||
|
||||
private void ListenForClients()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
clientHandle = CreateNamedPipe(pipeName, DUPLEX | FILE_FLAG_OVERLAPPED, 0, 255, BUFFER_SIZE, BUFFER_SIZE,
|
||||
0, IntPtr.Zero);
|
||||
//could not create named pipe
|
||||
if (clientHandle.IsInvalid)
|
||||
return;
|
||||
|
||||
var success = ConnectNamedPipe(clientHandle, IntPtr.Zero);
|
||||
|
||||
//could not connect client
|
||||
if (success == 0)
|
||||
return;
|
||||
|
||||
clientse = new Client();
|
||||
clientse.handle = clientHandle;
|
||||
clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
|
||||
|
||||
if (ClientType == 0)
|
||||
{
|
||||
var readThread = new Thread(Read);
|
||||
readThread.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Read()
|
||||
{
|
||||
//Client client = (Client)clientObj;
|
||||
//clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
|
||||
byte[] buffer = null;
|
||||
var encoder = new ASCIIEncoding();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
buffer = new byte[BUFFER_SIZE];
|
||||
bytesRead = clientse.stream.Read(buffer, 0, BUFFER_SIZE);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//read error has occurred
|
||||
break;
|
||||
}
|
||||
|
||||
//client has disconnected
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
|
||||
//fire message received event
|
||||
//if (this.MessageReceived != null)
|
||||
// this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
|
||||
|
||||
var ReadLength = 0;
|
||||
for (var i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
if (buffer[i].ToString("x2") != "cc")
|
||||
{
|
||||
ReadLength++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (ReadLength > 0)
|
||||
{
|
||||
var Rc = new byte[ReadLength];
|
||||
Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
|
||||
OnPipeDataReceived(new PipeDataReceivedEventArgs(encoder.GetString(Rc, 0, ReadLength)));
|
||||
|
||||
buffer.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
//clean up resources
|
||||
clientse.stream.Close();
|
||||
clientse.handle.Close();
|
||||
}
|
||||
|
||||
public void SendMessage(string message, Client client)
|
||||
{
|
||||
var encoder = new ASCIIEncoding();
|
||||
var messageBuffer = encoder.GetBytes(message);
|
||||
|
||||
if (client.stream.CanWrite)
|
||||
{
|
||||
client.stream.Write(messageBuffer, 0, messageBuffer.Length);
|
||||
client.stream.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopServer()
|
||||
{
|
||||
//clean up resources
|
||||
|
||||
DisconnectNamedPipe(clientHandle);
|
||||
|
||||
|
||||
listenThread.Abort();
|
||||
}
|
||||
|
||||
private void OnPipeDataReceived(PipeDataReceivedEventArgs e)
|
||||
{
|
||||
PipeDataReceived?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public class Client
|
||||
{
|
||||
public SafeFileHandle handle;
|
||||
public FileStream stream;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void PipeDataReceivedEventHandler(
|
||||
object sender, PipeDataReceivedEventArgs pipeDataReceivedEventArgs);
|
||||
|
||||
public class PipeDataReceivedEventArgs
|
||||
{
|
||||
public PipeDataReceivedEventArgs(string data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public string Data { get; set; }
|
||||
}
|
||||
}
|
||||
@ -15,12 +15,12 @@ namespace Artemis.Utilities
|
||||
{
|
||||
public static class Updater
|
||||
{
|
||||
public static int CurrentVersion = 120;
|
||||
public static int CurrentVersion = 1211;
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static async Task<Action> CheckForUpdate(MetroDialogService dialogService)
|
||||
{
|
||||
Logger.Info("Checking for updates - Current version: 1.2.0");
|
||||
Logger.Info("Checking for updates - Current version: 1.2.1.1 beta");
|
||||
if (!General.Default.CheckForUpdates)
|
||||
return null;
|
||||
|
||||
|
||||
@ -132,7 +132,7 @@ namespace Artemis.ViewModels
|
||||
|
||||
var dialog = await DialogService.ShowProgressDialog("Enabling keyboard",
|
||||
"Artemis is still busy trying to enable your last used keyboard. " +
|
||||
"Please wait while the progress completes");
|
||||
"Please wait while the process completes");
|
||||
dialog.SetIndeterminate();
|
||||
|
||||
while (MainManager.DeviceManager.ChangingKeyboard)
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" x:Name="ActiveEffectName" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.2.0" VerticalAlignment="Center"
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Artemis 1.2.1.1 beta" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left" />
|
||||
<Button Grid.Row="1" Grid.Column="1" Focusable="False"
|
||||
Style="{StaticResource AccentedSquareButtonStyle}"
|
||||
|
||||
@ -1,35 +1,29 @@
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <Windows.h>
|
||||
#include <filesystem>
|
||||
|
||||
TCHAR szName[] = TEXT("overwatchMmf");
|
||||
TCHAR szMsg[] = TEXT("Message from first process.");
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define BUF_SIZE 4096
|
||||
|
||||
static bool g_hasInitialised = false;
|
||||
const char* game = "";
|
||||
//const char* game = "";
|
||||
|
||||
|
||||
HANDLE hMapFile;
|
||||
HANDLE pipe;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// Get the process that loaded the DLL
|
||||
TCHAR overwatchFind[] = _T("Overwatch");
|
||||
TCHAR szPath[MAX_PATH];
|
||||
GetModuleFileName(nullptr, szPath, MAX_PATH);
|
||||
|
||||
if (_tcscmp(szPath, overwatchFind) != 0)
|
||||
game = "overwatch";
|
||||
|
||||
// Setup mmf
|
||||
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, BUF_SIZE, szName);
|
||||
// // Get the process that loaded the DLL
|
||||
// TCHAR overwatchFind[] = _T("Overwatch");
|
||||
// TCHAR szPath[MAX_PATH];
|
||||
// GetModuleFileName(nullptr, szPath, MAX_PATH);
|
||||
//
|
||||
// if (_tcscmp(szPath, overwatchFind) != 0)
|
||||
// game = "overwatch";
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -45,24 +39,16 @@ std::string string_format(const std::string& format, Args ... args)
|
||||
}
|
||||
|
||||
|
||||
void WriteMmf(std::string msg)
|
||||
void WritePipe(std::string msg)
|
||||
{
|
||||
if (hMapFile == nullptr)
|
||||
pipe = CreateFile(TEXT("\\\\.\\pipe\\artemis"), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
|
||||
if (pipe == nullptr || pipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LPCTSTR pBuf;
|
||||
pBuf = static_cast<LPTSTR>(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE));
|
||||
|
||||
if (pBuf == nullptr)
|
||||
{
|
||||
CloseHandle(hMapFile);
|
||||
return;
|
||||
}
|
||||
|
||||
CopyMemory((PVOID)pBuf, msg.c_str(), msg.size());
|
||||
UnmapViewOfFile(pBuf);
|
||||
DWORD cbWritten;
|
||||
WriteFile(pipe, msg.c_str(), msg.size(), &cbWritten, nullptr);
|
||||
}
|
||||
|
||||
RZRESULT Init()
|
||||
@ -117,7 +103,7 @@ RZRESULT CreateKeyboardEffect(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM
|
||||
}
|
||||
}
|
||||
|
||||
WriteMmf(res);
|
||||
WritePipe(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user