diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 9a20f58be..c3848c7c9 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -163,10 +163,6 @@
False
-
- ..\packages\NamedPipeWrapper.1.4.0\lib\net40\NamedPipeWrapper.dll
- True
-
..\packages\NAudio.1.7.3\lib\net35\NAudio.dll
True
@@ -371,7 +367,8 @@
-
+
+
diff --git a/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs b/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs
index 87495914c..b3e1bd9ed 100644
--- a/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs
+++ b/Artemis/Artemis/KeyboardProviders/Logitech/Utilities/LogitechGSDK.cs
@@ -68,7 +68,7 @@ namespace Artemis.KeyboardProviders.Logitech.Utilities
int greenPercentage, int bluePercentage);
[DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)]
- public static extern bool LogiLedSetLightingForKeyWithKeyName(KeyboardNames keyCode, int redPercentage,
+ public static extern bool LogiLedSetLightingForKeyWithKeyName(int keyCode, int redPercentage,
int greenPercentage, int bluePercentage);
[DllImport("LogitechLedEnginesWrapper ", CallingConvention = CallingConvention.Cdecl)]
diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs
index 444aa2c88..79e394518 100644
--- a/Artemis/Artemis/Managers/MainManager.cs
+++ b/Artemis/Artemis/Managers/MainManager.cs
@@ -2,11 +2,13 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
+using System.Windows.Forms;
using Artemis.Events;
using Artemis.Models;
using Artemis.Services;
using Artemis.Utilities.GameState;
using Artemis.Utilities.Keyboard;
+using Artemis.Utilities.LogitechDll;
using Caliburn.Micro;
namespace Artemis.Managers
@@ -47,8 +49,13 @@ namespace Artemis.Managers
// Create and start the web server
GameStateWebServer = new GameStateWebServer();
GameStateWebServer.Start();
+
+ // Start the named pipe
+ PipeServer = new PipeServer();
+ PipeServer.Start("artemis");
}
+ public PipeServer PipeServer { get; set; }
public BackgroundWorker UpdateWorker { get; set; }
public BackgroundWorker ProcessWorker { get; set; }
@@ -65,6 +72,7 @@ namespace Artemis.Managers
public bool Suspended { get; set; }
public bool Running { get; private set; }
+
public event PauseCallbackHandler PauseCallback;
///
@@ -137,7 +145,9 @@ namespace Artemis.Managers
{
Stop();
ProcessWorker.CancelAsync();
+ ProcessWorker.CancelAsync();
GameStateWebServer.Stop();
+ //NamedPipeServer.StopServer();
}
public void Restart()
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
index a8b25b42e..92dc1a9a6 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs
@@ -1,6 +1,10 @@
-using System.Drawing;
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using Artemis.KeyboardProviders.Logitech.Utilities;
using Artemis.Managers;
using Artemis.Models;
+using Artemis.Utilities.LogitechDll;
namespace Artemis.Modules.Games.TheDivision
{
@@ -23,17 +27,42 @@ namespace Artemis.Modules.Games.TheDivision
public override void Dispose()
{
Initialized = false;
+ DllManager.RestoreDll();
}
public override void Enable()
{
Initialized = false;
-
- // Enable logic, if any
-
+ DllManager.PlaceDll();
+ MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
}
+ private void PipeServerOnPipeMessage(string reply)
+ {
+ // Convert the given string to a list of ints
+ var stringParts = reply.Split(' ');
+ var parts = new int[stringParts.Length];
+ for (var i = 0; i < stringParts.Length; i++)
+ parts[i] = int.Parse(stringParts[i]);
+
+ if (parts[0] == 1)
+ InterpertrateDivisionKey(parts);
+
+ }
+
+ // Parses Division key data to game data
+ private void InterpertrateDivisionKey(int[] parts)
+ {
+ // F1 to F4 indicate the player and his party. Blinks red on damage taken
+
+ // R blinks white when low on ammo
+
+ // G turns white when holding a grenade, turns off when out of grenades
+
+ // V blinks on low HP
+ }
+
public override void Update()
{
}
diff --git a/Artemis/Artemis/Resources/LogitechLED.dll b/Artemis/Artemis/Resources/LogitechLED.dll
index 9ecba3c77..2d722626e 100644
Binary files a/Artemis/Artemis/Resources/LogitechLED.dll and b/Artemis/Artemis/Resources/LogitechLED.dll differ
diff --git a/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs b/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs
index 1485c2272..739968f69 100644
--- a/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs
+++ b/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs
@@ -10,14 +10,17 @@ namespace Artemis.Utilities.LogitechDll
public static bool RestoreDll()
{
- if (!File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
+ if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt"))
return false;
-
+
// Get rid of our own DLL
File.Delete(LogitechPath + @"\LogitechLed.dll");
+
// Restore the backup
- File.Move(LogitechPath + @"\LogitechLed.dll.bak",
- LogitechPath + @"\LogitechLed.dll");
+ if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
+ File.Move(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll");
+
+ File.Delete(LogitechPath + @"\artemis.txt");
return true;
}
@@ -43,6 +46,9 @@ namespace Artemis.Utilities.LogitechDll
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())
@@ -56,7 +62,7 @@ namespace Artemis.Utilities.LogitechDll
if (!RegistryKeyPlaced())
return false;
- return File.Exists(LogitechPath + @"\LogitechLed.dll");
+ return File.Exists(LogitechPath + @"\artemis.txt");
}
private static bool RegistryKeyPlaced()
diff --git a/Artemis/Artemis/Utilities/LogitechDll/LogitechNamedPipe.cs b/Artemis/Artemis/Utilities/LogitechDll/LogitechNamedPipe.cs
deleted file mode 100644
index 99a2bbfef..000000000
--- a/Artemis/Artemis/Utilities/LogitechDll/LogitechNamedPipe.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Diagnostics;
-using NamedPipeWrapper;
-
-namespace Artemis.Utilities.LogitechDll
-{
- public class LogitechNamedPipe
- {
- public LogitechNamedPipe()
- {
- LogitechPipe = new NamedPipeServer("ArtemisLogitech");
-
- LogitechPipe.ClientMessage += LogitechPipeOnClientMessage;
- LogitechPipe.Start();
- }
-
- public NamedPipeServer LogitechPipe { get; set; }
-
- private void LogitechPipeOnClientMessage(NamedPipeConnection connection, string message)
- {
- Debug.WriteLine(message);
- }
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs b/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs
new file mode 100644
index 000000000..5557ad0bf
--- /dev/null
+++ b/Artemis/Artemis/Utilities/LogitechDll/NamedPipeServer.cs
@@ -0,0 +1,189 @@
+using System;
+using System.IO;
+using System.IO.Pipes;
+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; }
+ }
+
+
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs
new file mode 100644
index 000000000..bb0ac497e
--- /dev/null
+++ b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs
@@ -0,0 +1,132 @@
+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, 100,
+ PipeTransmissionMode.Byte, PipeOptions.None, 100, 100, security);
+
+ namedPipeServerStream.WaitForConnection();
+ var buffer = new byte[100];
+ namedPipeServerStream.Read(buffer, 0, 100);
+ 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, 100, PipeTransmissionMode.Byte,
+ PipeOptions.Asynchronous, 100, 100, 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);
+ Debug.WriteLine(stringData + Environment.NewLine);
+
+ // 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, 100, PipeTransmissionMode.Byte,
+ PipeOptions.Asynchronous, 100, 100, security);
+
+ // Recursively wait for the connection again and again....
+ pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/packages.config b/Artemis/Artemis/packages.config
index d5231ab31..0b67a3431 100644
--- a/Artemis/Artemis/packages.config
+++ b/Artemis/Artemis/packages.config
@@ -12,7 +12,6 @@
-