136 lines
4.4 KiB
C#
136 lines
4.4 KiB
C#
using EasyPipes;
|
|
using SoraV2Tools;
|
|
using System;
|
|
using System.IO;
|
|
using System.IO.Pipes;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.AccessControl;
|
|
using System.Security.Principal;
|
|
|
|
namespace SoraV2Utils_Service
|
|
{
|
|
// Interface for mouse data interaction
|
|
public interface IMouseData
|
|
{
|
|
byte[] GetDeviceStatus();
|
|
double GetBatteryRuntime();
|
|
void Exit();
|
|
}
|
|
|
|
public class ServiceIPC
|
|
{
|
|
// Creates pipe security for system IO
|
|
private PipeSecurity CreateSystemIOPipeSecurity()
|
|
{
|
|
PipeSecurity pipeSecurity = new PipeSecurity();
|
|
|
|
// Assign authenticated user read-write access
|
|
var authenticatedUserSid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
|
|
pipeSecurity.SetAccessRule(new PipeAccessRule(authenticatedUserSid, PipeAccessRights.ReadWrite, AccessControlType.Allow));
|
|
|
|
return pipeSecurity;
|
|
}
|
|
|
|
// Opens a custom named pipe with the specified name and buffer size
|
|
private NamedPipeServerStream OpenCustomPipe(string pipeName, int bufferSize)
|
|
{
|
|
try
|
|
{
|
|
var pipeSecurity = CreateSystemIOPipeSecurity();
|
|
var pipeStream = new NamedPipeServerStream(pipeName,
|
|
PipeDirection.InOut,
|
|
1,
|
|
PipeTransmissionMode.Message,
|
|
PipeOptions.Asynchronous,
|
|
bufferSize,
|
|
0x400,
|
|
pipeSecurity,
|
|
HandleInheritability.Inheritable);
|
|
|
|
Console.WriteLine($"Named Pipe '{pipeName}' successfully opened.");
|
|
return pipeStream;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Error opening pipe {pipeName}: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Constructor for initializing the IPC service and server
|
|
public ServiceIPC()
|
|
{
|
|
try
|
|
{
|
|
var server = new Server("SoraV2UtilsDeviceData", OpenCustomPipe);
|
|
server.RegisterService<IMouseData>(new ServiceIPCHandler());
|
|
server.Start();
|
|
Console.WriteLine("IPC Service started successfully.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Failed to start IPC Service: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handler class to implement the IMouseData interface
|
|
public class ServiceIPCHandler : IMouseData
|
|
{
|
|
public byte[] GetDeviceStatus()
|
|
{
|
|
var status = DeviceTracker.Instance._DeviceStatus;
|
|
try
|
|
{
|
|
int size = Marshal.SizeOf(status);
|
|
byte[] arr = new byte[size];
|
|
|
|
IntPtr ptr = IntPtr.Zero;
|
|
try
|
|
{
|
|
ptr = Marshal.AllocHGlobal(size);
|
|
Marshal.StructureToPtr(status, ptr, true);
|
|
Marshal.Copy(ptr, arr, 0, size);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(ptr);
|
|
}
|
|
return arr;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Error retrieving battery level: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public double GetBatteryRuntime()
|
|
{
|
|
try
|
|
{
|
|
return DeviceTracker.Instance?.EstimateRemainingRuntime() ?? 0.0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Error estimating battery runtime: {ex.Message}");
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
public void Exit()
|
|
{
|
|
try
|
|
{
|
|
// Exit the application with code 1
|
|
Console.WriteLine("Exiting application...");
|
|
Environment.Exit(1);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.Error.WriteLine($"Error during exit: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
}
|