// // CommsInjector.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using NosSmooth.Comms.Core; using NosSmooth.Comms.Core.NamedPipes; using NosSmooth.Comms.Data; using NosSmooth.Comms.Inject; using NosSmooth.Injector; using NosSmooth.LocalBinding; using NosSmooth.LocalBinding.Options; using Remora.Results; namespace NosSmooth.Comms.Local; /// /// Injects communication (tcp or named pipes) into a nostale process. /// public class CommsInjector { private readonly IServiceProvider _serviceProvider; private readonly NosInjector _injector; private readonly NostaleClientResolver _resolver; /// /// Initializes a new instance of the class. /// /// The service provider. /// The injector. /// The nostale client resolver. public CommsInjector(IServiceProvider serviceProvider, NosInjector injector, NostaleClientResolver resolver) { _serviceProvider = serviceProvider; _injector = injector; _resolver = resolver; } /// /// Find processes that are NosTale and create a from them. /// /// The names to filter when searching the processes. In case the array is empty, look for all processes. /// A list of the NosTale processes. public static IEnumerable> CreateNostaleProcesssesBrowsers(params string[] filterNames) { return FindNosTaleProcesses(filterNames) .Select ( x => { var manager = new NosBrowserManager ( x, new PlayerManagerOptions(), new SceneManagerOptions(), new PetManagerOptions(), new NetworkManagerOptions(), new UnitManagerOptions() ); var initResult = manager.Initialize(); if (!initResult.IsSuccess) { return Result.FromError(initResult.Error); } return manager; } ); } /// /// Find processes that are NosTale. /// /// The names to filter when searching the processes. In case the array is empty, look for all processes. /// A list of the NosTale processes. public static IEnumerable FindNosTaleProcesses(params string[] filterNames) { var processes = Process.GetProcesses().AsEnumerable(); if (filterNames.Length > 0) { processes = processes.Where(x => filterNames.Contains(x.ProcessName)); } return processes .Where ( x => { try { return NosBrowserManager.IsProcessNostaleProcess(x); } catch { return false; } } ); } /// /// Inject NosSmooth.Comms.Inject.dll into the process, /// enable tcp server and establish a connection to the server. /// /// The result containing information about the established connection. public Task> EstablishTcpConnectionAsync() { throw new NotImplementedException(); } /// /// Inject NosSmooth.Comms.Inject.dll into the process, /// enable named pipes server and establish a connection to the server. /// /// The process to establish named pipes with. /// The token used for stopping the connection. /// The cancellation token used for cancelling the operation. /// The result containing information about the established connection. public async Task> EstablishNamedPipesConnectionAsync (Process process, CancellationToken stopToken, CancellationToken ct) { var injectResult = Inject(process, nameof(DllMain.EnableNamedPipes)); if (!injectResult.IsSuccess) { return Result.FromError(injectResult); } var namedPipeClient = new NamedPipeClient($"NosSmooth_{process.Id}"); var connectionResult = await namedPipeClient.ConnectAsync(ct); if (!connectionResult.IsSuccess) { return Result.FromError(connectionResult); } var handler = ActivatorUtilities.CreateInstance (_serviceProvider, (IConnection)namedPipeClient); handler.StartHandler(stopToken); var nostaleClient = _resolver.Resolve(handler); return new Comms(process, handler, nostaleClient); } /// /// Open a console in the target process. /// /// /// Log of inject will be printed to the console. /// /// The process. /// A result that may or may not have succeeded. public Result OpenConsole(Process process) { return Inject(process, nameof(DllMain.OpenConsole)); } /// /// Close a console in the target process. /// /// The process. /// A result that may or may not have succeeded. public Result CloseConsole(Process process) { return Inject(process, nameof(DllMain.CloseConsole)); } private Result Inject(Process process, string method) { return _injector.Inject ( process, Path.GetFullPath("NosSmooth.Comms.Inject.dll"), "NosSmooth.Comms.Inject.DllMain, NosSmooth.Comms.Inject", method ); } }