From 560a39a70b8046b8d808e14d102c3b4a29b0a5e9 Mon Sep 17 00:00:00 2001 From: AeonLucid Date: Sat, 30 Oct 2021 04:40:10 +0200 Subject: [PATCH] Add DLL to modify PlayFab url --- src/Prospect.Agent/Prospect.Agent.vcxproj | 25 +++-- .../Prospect.Agent.vcxproj.filters | 10 +- src/Prospect.Agent/SDK.h | 96 ++++++++++++++++++ src/Prospect.Agent/SDK_Memory.h | 79 ++++++++++++++ src/Prospect.Agent/hooks.h | 3 + src/Prospect.Agent/logger.cpp | 3 + src/Prospect.Agent/logger.h | 5 +- src/Prospect.Agent/main.cpp | 74 ++++++++++++-- src/Prospect.Agent/main.h | 4 - src/Prospect.Launcher/Inject.cs | 56 ++++++++++ src/Prospect.Launcher/Invoke/Kernel32.cs | 18 ++++ src/Prospect.Launcher/Libs/Prospect.Agent.dll | Bin 0 -> 27648 bytes src/Prospect.Launcher/MemoryHelper.cs | 11 +- src/Prospect.Launcher/Program.cs | 25 +++-- .../Prospect.Launcher.csproj | 10 ++ src/Prospect.Server.Api/Program.cs | 45 ++++++++ .../Properties/launchSettings.json | 13 +++ .../Prospect.Server.Api.csproj | 11 ++ src/Prospect.Server.Api/Startup.cs | 33 ++++++ .../appsettings.Development.json | 2 + src/Prospect.Server.Api/appsettings.json | 2 + src/Prospect.sln | 10 ++ src/Prospect.sln.DotSettings | 6 ++ 23 files changed, 501 insertions(+), 40 deletions(-) create mode 100644 src/Prospect.Agent/SDK.h create mode 100644 src/Prospect.Agent/SDK_Memory.h create mode 100644 src/Prospect.Agent/hooks.h delete mode 100644 src/Prospect.Agent/main.h create mode 100644 src/Prospect.Launcher/Inject.cs create mode 100644 src/Prospect.Launcher/Libs/Prospect.Agent.dll create mode 100644 src/Prospect.Server.Api/Program.cs create mode 100644 src/Prospect.Server.Api/Properties/launchSettings.json create mode 100644 src/Prospect.Server.Api/Prospect.Server.Api.csproj create mode 100644 src/Prospect.Server.Api/Startup.cs create mode 100644 src/Prospect.Server.Api/appsettings.Development.json create mode 100644 src/Prospect.Server.Api/appsettings.json create mode 100644 src/Prospect.sln.DotSettings diff --git a/src/Prospect.Agent/Prospect.Agent.vcxproj b/src/Prospect.Agent/Prospect.Agent.vcxproj index 26c6237..a4b111e 100644 --- a/src/Prospect.Agent/Prospect.Agent.vcxproj +++ b/src/Prospect.Agent/Prospect.Agent.vcxproj @@ -47,13 +47,21 @@ true - $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)Prospect.Launcher\Libs $(ProjectDir)bin\intermediate\$(Platform)\$(Configuration)\ + $(LibraryPath) false - $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)Prospect.Launcher\Libs $(ProjectDir)bin\intermediate\$(Platform)\$(Configuration)\ + $(LibraryPath) + + + true + + + true @@ -63,13 +71,13 @@ true NotUsing pch.h - $(ProjectDir)libs\detours\;$(UESDK);%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) Windows true false - detours.lib;%(AdditionalDependencies) + %(AdditionalDependencies) @@ -82,7 +90,8 @@ true NotUsing pch.h - $(ProjectDir)libs\detours\;$(UESDK);%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + MinSpace Windows @@ -90,12 +99,14 @@ true true false - detours.lib;%(AdditionalDependencies) + %(AdditionalDependencies) + - + + diff --git a/src/Prospect.Agent/Prospect.Agent.vcxproj.filters b/src/Prospect.Agent/Prospect.Agent.vcxproj.filters index 9bd498c..4f007b6 100644 --- a/src/Prospect.Agent/Prospect.Agent.vcxproj.filters +++ b/src/Prospect.Agent/Prospect.Agent.vcxproj.filters @@ -15,10 +15,16 @@ - + Header Files - + + Header Files + + + Header Files + + Header Files diff --git a/src/Prospect.Agent/SDK.h b/src/Prospect.Agent/SDK.h new file mode 100644 index 0000000..86cea59 --- /dev/null +++ b/src/Prospect.Agent/SDK.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include "SDK_Memory.h" + +namespace SDK +{ + template + struct TArray + { + friend struct FString; + + TArray() + { + Data = nullptr; + Count = Max = 0; + } + + int Num() const + { + return Count; + } + + T& operator[](int i) + { + return Data[i]; + } + + const T& operator[](int i) const + { + return Data[i]; + } + + bool IsValidIndex(int i) const + { + return i < Num(); + } + + private: + T* Data; + int32_t Count; + int32_t Max; + }; + + struct FString : private TArray + { + FString(const wchar_t* other) + { + Max = Count = *other ? std::wcslen(other) + 1 : 0; + + if (Count) + { + Data = static_cast(GMalloc->Malloc(Count)); + + wcscpy_s(Data, Count, other); + } + } + + FString(const std::wstring& other) : FString(other.c_str()) + { + + } + + bool IsValid() const + { + return Data != nullptr; + } + + const wchar_t* c_str() const + { + return Data; + } + + std::string ToString() const + { + const auto length = std::wcslen(Data); + + std::string str(length, '\0'); + std::use_facet>(std::locale()).narrow(Data, Data + length, '?', &str[0]); + + return str; + } + }; + + struct UPlayFabAPISettings + { + FString VerticalName; + FString BaseServiceHost; + FString TitleId; + FString AdvertisingIdType; + FString AdvertisingIdValue; + bool DisableAdvertising = false; + }; +} diff --git a/src/Prospect.Agent/SDK_Memory.h b/src/Prospect.Agent/SDK_Memory.h new file mode 100644 index 0000000..af651a9 --- /dev/null +++ b/src/Prospect.Agent/SDK_Memory.h @@ -0,0 +1,79 @@ +#pragma once + +#include + +#define DEFAULT_ALIGNMENT 0 + +namespace SDK +{ + class FExec + { + public: + virtual ~FExec() = default; + private: + virtual bool Exec(void* world, void* cmd, void* ar) = 0; + }; + + class FMalloc : FExec + { + public: + virtual void* Malloc(SIZE_T Count, uint32_t Alignment = DEFAULT_ALIGNMENT) = 0; + + virtual void* TryMalloc(SIZE_T Count, uint32_t Alignment = DEFAULT_ALIGNMENT) = 0; + + virtual void* Realloc(void* Original, SIZE_T Count, uint32_t Alignment = DEFAULT_ALIGNMENT) = 0; + + virtual void* TryRealloc(void* Original, SIZE_T Count, uint32_t Alignment = DEFAULT_ALIGNMENT) = 0; + + virtual void Free(void* Original) = 0; + + virtual SIZE_T QuantizeSize(SIZE_T Count, uint32_t Alignment) + { + return Count; + } + + virtual bool GetAllocationSize(void* Original, SIZE_T& SizeOut) + { + return false; + } + + virtual void Trim(bool bTrimThreadCaches) + { + } + + virtual void SetupTLSCachesOnCurrentThread() + { + } + + virtual void ClearAndDisableTLSCachesOnCurrentThread() + { + } + + virtual void InitializeStatsMetadata(); + + virtual bool Exec(void* InWorld, void* Cmd, void* Ar) override + { + return false; + } + + virtual void UpdateStats() = 0; + + virtual void GetAllocatorStats(void* out_Stats) = 0; + + virtual void DumpAllocatorStats(class FOutputDevice& Ar) = 0; + + virtual bool IsInternallyThreadSafe() const + { + return false; + } + + virtual bool ValidateHeap() + { + return(true); + } + + virtual const TCHAR* GetDescriptiveName() = 0; + }; + + FMalloc* GMalloc; +} diff --git a/src/Prospect.Agent/hooks.h b/src/Prospect.Agent/hooks.h new file mode 100644 index 0000000..4e2a47a --- /dev/null +++ b/src/Prospect.Agent/hooks.h @@ -0,0 +1,3 @@ +#pragma once + +#include "SDK.h" \ No newline at end of file diff --git a/src/Prospect.Agent/logger.cpp b/src/Prospect.Agent/logger.cpp index 296a0a2..24eed78 100644 --- a/src/Prospect.Agent/logger.cpp +++ b/src/Prospect.Agent/logger.cpp @@ -1,5 +1,8 @@ #include "logger.h" +#include +#include + HANDLE h_out = nullptr, h_old_out = nullptr; HANDLE h_err = nullptr, h_old_err = nullptr; HANDLE h_in = nullptr, h_old_in = nullptr; diff --git a/src/Prospect.Agent/logger.h b/src/Prospect.Agent/logger.h index 14ebd2e..9317173 100644 --- a/src/Prospect.Agent/logger.h +++ b/src/Prospect.Agent/logger.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - namespace logger { void Attach(); @@ -12,4 +9,4 @@ namespace logger bool Print(const char* fmt, ...); char ReadKey(); -}; +} \ No newline at end of file diff --git a/src/Prospect.Agent/main.cpp b/src/Prospect.Agent/main.cpp index 0bf88c3..aa2db4d 100644 --- a/src/Prospect.Agent/main.cpp +++ b/src/Prospect.Agent/main.cpp @@ -1,17 +1,71 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include #include -#include "main.h" #include "logger.h" -#include +#include "SDK.h" +#include "SDK_Memory.h" + +/** + * Variable offset, find with "STOPMOVIECAPTURE", scroll up. + */ +constexpr uintptr_t OffsetGMalloc = 0x5C9A3F8; + +/** + * Function offset, find with "?sdk=". + */ +constexpr uintptr_t OffsetPlayFabApiGetUrl = 0xCA5010; + +/** + * Function hooks. + */ +typedef SDK::FString(__fastcall* tPlayFabApiGetUrl)(SDK::UPlayFabAPISettings*, const SDK::FString&); + +tPlayFabApiGetUrl OldPlayFabApiGetUrl; + +SDK::FString __fastcall PlayFabApiGetUrlProxy(SDK::UPlayFabAPISettings* thiz, const SDK::FString& callPath) +{ + logger::Print("[Agent] GetURL called with callPath %s\n", callPath.ToString().c_str()); + + return std::wstring(L"http://127.0.0.1:8888") + std::wstring(callPath.c_str()); +} DWORD WINAPI OnDllAttach(LPVOID base) { - logger::Attach(); logger::Print("[Agent] DLL Attached\n"); - // TODO: Patch. + const auto hModule = GetModuleHandleW(nullptr); + const auto hModulePtr = reinterpret_cast(hModule); - logger::Print("[Agent] DLL Exit\n"); - FreeLibraryAndExitThread(static_cast(base), 1); + // Initialize GMalloc. + SDK::GMalloc = *reinterpret_cast(hModulePtr + OffsetGMalloc); + + // Initialize MinHook. + if (MH_Initialize() != MH_OK) + { + logger::Print("[Agent] Failed to initialize MinHook\n"); + FreeLibraryAndExitThread(hModule, 1); + } + + // Hook UPlayFabAPISettings::GetUrl. + const auto pTarget = reinterpret_cast(hModulePtr + OffsetPlayFabApiGetUrl); + const auto ppOriginal = reinterpret_cast(&OldPlayFabApiGetUrl); + const auto mhStatus = MH_CreateHook(pTarget, &PlayFabApiGetUrlProxy, ppOriginal); + + if (mhStatus != MH_OK) + { + logger::Print("[Agent] Failed to create PlayFabAPIGetUrl hook (%d)\n", mhStatus); + FreeLibraryAndExitThread(hModule, 1); + } + + if (MH_EnableHook(pTarget) != MH_OK) + { + logger::Print("[Agent] Failed to enable PlayFabAPIGetUrl hook\n"); + FreeLibraryAndExitThread(hModule, 1); + } + + logger::Print("[Agent] DLL Initialized\n"); + ExitThread(1); } BOOL WINAPI DllMain( @@ -27,10 +81,18 @@ BOOL WINAPI DllMain( // Allocate a console. AllocConsole(); freopen_s(reinterpret_cast(stdout), "CONOUT$", "w", stdout); + + // Attach logger. + logger::Attach(); // Spawn thread. CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr); } + else if (fdwReason == DLL_PROCESS_DETACH) + { + // Detach logger. + logger::Detach(); + } return TRUE; } diff --git a/src/Prospect.Agent/main.h b/src/Prospect.Agent/main.h deleted file mode 100644 index 5cb4cbf..0000000 --- a/src/Prospect.Agent/main.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include diff --git a/src/Prospect.Launcher/Inject.cs b/src/Prospect.Launcher/Inject.cs new file mode 100644 index 0000000..6179c19 --- /dev/null +++ b/src/Prospect.Launcher/Inject.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using Prospect.Launcher.Invoke; + +namespace Prospect.Launcher +{ + public static class Inject + { + const int PROCESS_CREATE_THREAD = 0x0002; + const int PROCESS_QUERY_INFORMATION = 0x0400; + const int PROCESS_VM_OPERATION = 0x0008; + const int PROCESS_VM_WRITE = 0x0020; + const int PROCESS_VM_READ = 0x0010; + + const uint MEM_COMMIT = 0x00001000; + const uint MEM_RESERVE = 0x00002000; + const uint PAGE_READWRITE = 4; + + // https://codingvision.net/c-inject-a-dll-into-a-process-w-createremotethread + public static unsafe bool Library(uint processId, string path) + { + IntPtr procHandle = Kernel32.OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, (int)processId); + + var loadLibraryAddr = Kernel32.GetProcAddress(Kernel32.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); + if (loadLibraryAddr == IntPtr.Zero) + { + Console.WriteLine("Failed GetProcAddress."); + return false; + } + + var allocMemAddress = Kernel32.VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((path.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (allocMemAddress == IntPtr.Zero) + { + Console.WriteLine("Failed VirtualAllocEx."); + return false; + } + + var libraryBytes = Encoding.Default.GetBytes(path); + + fixed (byte* pLibraryBytes = libraryBytes) + { + Kernel32.WriteProcessMemory(procHandle, allocMemAddress, pLibraryBytes, libraryBytes.Length + 1, out _); + } + + var threadHandle = Kernel32.CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero); + if (threadHandle == IntPtr.Zero) + { + Console.WriteLine("Failed CreateRemoteThread."); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/src/Prospect.Launcher/Invoke/Kernel32.cs b/src/Prospect.Launcher/Invoke/Kernel32.cs index dc58b1e..e2268be 100644 --- a/src/Prospect.Launcher/Invoke/Kernel32.cs +++ b/src/Prospect.Launcher/Invoke/Kernel32.cs @@ -42,5 +42,23 @@ namespace Prospect.Launcher.Invoke [DllImport("kernel32.dll", SetLastError = true)] public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr GetModuleHandle(string lpModuleName); + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); + + [DllImport("kernel32.dll")] + public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern uint ResumeThread(IntPtr hThread); } } \ No newline at end of file diff --git a/src/Prospect.Launcher/Libs/Prospect.Agent.dll b/src/Prospect.Launcher/Libs/Prospect.Agent.dll new file mode 100644 index 0000000000000000000000000000000000000000..49738f1317c9546c13c25b675f21900643857819 GIT binary patch literal 27648 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 data) + public unsafe void Write(int offset, ReadOnlySpan data) + { + Write(_baseAddress + offset, data); + } + + public unsafe void Write(IntPtr addr, ReadOnlySpan data) { - var addr = _baseAddress + offset; - // Modify protection. if (!Kernel32.VirtualProtectEx(_handle, addr, data.Length, 0x40, out var oldProtect)) { @@ -56,7 +59,7 @@ namespace Prospect.Launcher fixed (byte* pData = data) { - var write = Kernel32.WriteProcessMemory(_handle, _baseAddress + offset, pData, data.Length, out _); + var write = Kernel32.WriteProcessMemory(_handle, addr, pData, data.Length, out _); // Restore protection. Kernel32.VirtualProtectEx(_handle, addr, data.Length, oldProtect, out _); diff --git a/src/Prospect.Launcher/Program.cs b/src/Prospect.Launcher/Program.cs index c01e094..0c53df1 100644 --- a/src/Prospect.Launcher/Program.cs +++ b/src/Prospect.Launcher/Program.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Threading; using Prospect.Launcher.Invoke; using Prospect.Launcher.Invoke.Structs; @@ -33,6 +32,7 @@ namespace Prospect.Launcher // 2EA46 = Default // A22AB = The Cycle Playtest + gameArgs.Add("-empty"); gameArgs.Add("-log"); gameArgs.Add("-windowed"); gameArgs.Add("-noeac"); @@ -51,7 +51,7 @@ namespace Prospect.Launcher // Spawn. var startupInfo = new StartupInfo(); - if (!Kernel32.CreateProcess(gameBinary, string.Join(' ', gameArgs), ProcessCreationFlags.ZERO_FLAG, ref startupInfo, out var processInfo)) + if (!Kernel32.CreateProcess(gameBinary, string.Join(' ', gameArgs), ProcessCreationFlags.CREATE_SUSPENDED, ref startupInfo, out var processInfo)) { Console.WriteLine("Failed to spawn game."); return; @@ -59,22 +59,21 @@ namespace Prospect.Launcher Console.WriteLine("Spawned."); - // Modify. - MemoryHelper memory; - - while ((memory = MemoryHelper.CreateForHandle(processInfo.hProcess, gameBinary)) == null) - { - Console.WriteLine("Failed to obtain MemoryHelper."); - Thread.Sleep(100); - } + // Inject DLL. + var agentPath = Path.Combine(AppContext.BaseDirectory, "Libs", "Prospect.Agent.dll"); - if (!Patches.ChangePlayFabUrl(memory, ".localhost")) + if (!Inject.Library(processInfo.dwProcessId, agentPath)) { - Console.WriteLine("Failed to patch playfab url."); + Console.WriteLine("Failed to inject library."); return; } + + Console.WriteLine("Injected."); + + // Resume. + Kernel32.ResumeThread(processInfo.hThread); - Console.WriteLine("Patched."); + Console.WriteLine("Resumed."); } } } \ No newline at end of file diff --git a/src/Prospect.Launcher/Prospect.Launcher.csproj b/src/Prospect.Launcher/Prospect.Launcher.csproj index a1e2920..3595d26 100644 --- a/src/Prospect.Launcher/Prospect.Launcher.csproj +++ b/src/Prospect.Launcher/Prospect.Launcher.csproj @@ -14,4 +14,14 @@ x64 + + + + + + + PreserveNewest + + + diff --git a/src/Prospect.Server.Api/Program.cs b/src/Prospect.Server.Api/Program.cs new file mode 100644 index 0000000..ce0723e --- /dev/null +++ b/src/Prospect.Server.Api/Program.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace Prospect.Server.Api +{ + public static class Program + { + public static int Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); + + try + { + Log.Information("Starting web host"); + CreateHostBuilder(args).Build().Run(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } + + private static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseSerilog() + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} \ No newline at end of file diff --git a/src/Prospect.Server.Api/Properties/launchSettings.json b/src/Prospect.Server.Api/Properties/launchSettings.json new file mode 100644 index 0000000..be656e1 --- /dev/null +++ b/src/Prospect.Server.Api/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "Prospect.Server.Api": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "applicationUrl": "https://A22AB.localhost:5555", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Prospect.Server.Api/Prospect.Server.Api.csproj b/src/Prospect.Server.Api/Prospect.Server.Api.csproj new file mode 100644 index 0000000..6fab24b --- /dev/null +++ b/src/Prospect.Server.Api/Prospect.Server.Api.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/src/Prospect.Server.Api/Startup.cs b/src/Prospect.Server.Api/Startup.cs new file mode 100644 index 0000000..de03832 --- /dev/null +++ b/src/Prospect.Server.Api/Startup.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; + +namespace Prospect.Server.Api +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseSerilogRequestLogging(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} \ No newline at end of file diff --git a/src/Prospect.Server.Api/appsettings.Development.json b/src/Prospect.Server.Api/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/src/Prospect.Server.Api/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/Prospect.Server.Api/appsettings.json b/src/Prospect.Server.Api/appsettings.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/src/Prospect.Server.Api/appsettings.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/Prospect.sln b/src/Prospect.sln index 4d9c660..d4d1cb2 100644 --- a/src/Prospect.sln +++ b/src/Prospect.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Prospect.Agent", "Prospect. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prospect.Launcher", "Prospect.Launcher\Prospect.Launcher.csproj", "{1C8F4637-9552-4726-818B-196ECE2AE966}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prospect.Server.Api", "Prospect.Server.Api\Prospect.Server.Api.csproj", "{A539B020-8BEC-497F-9176-DC2665D927A1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -29,6 +31,14 @@ Global {1C8F4637-9552-4726-818B-196ECE2AE966}.Release|x64.Build.0 = Release|Any CPU {1C8F4637-9552-4726-818B-196ECE2AE966}.Release|x86.ActiveCfg = Release|Any CPU {1C8F4637-9552-4726-818B-196ECE2AE966}.Release|x86.Build.0 = Release|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Debug|x64.ActiveCfg = Debug|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Debug|x64.Build.0 = Debug|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Debug|x86.ActiveCfg = Debug|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Debug|x86.Build.0 = Debug|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Release|x64.ActiveCfg = Release|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Release|x64.Build.0 = Release|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Release|x86.ActiveCfg = Release|Any CPU + {A539B020-8BEC-497F-9176-DC2665D927A1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Prospect.sln.DotSettings b/src/Prospect.sln.DotSettings new file mode 100644 index 0000000..6f47746 --- /dev/null +++ b/src/Prospect.sln.DotSettings @@ -0,0 +1,6 @@ + + API + SDK + <NamingElement Priority="1"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="struct" /></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></NamingElement> + <NamingElement Priority="10"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="member function" /></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></NamingElement> + <NamingElement Priority="17"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="namespace" /><type Name="namespace alias" /></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></NamingElement> \ No newline at end of file