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 0000000..49738f1 Binary files /dev/null and b/src/Prospect.Launcher/Libs/Prospect.Agent.dll differ diff --git a/src/Prospect.Launcher/MemoryHelper.cs b/src/Prospect.Launcher/MemoryHelper.cs index d555494..cd503dd 100644 --- a/src/Prospect.Launcher/MemoryHelper.cs +++ b/src/Prospect.Launcher/MemoryHelper.cs @@ -44,10 +44,13 @@ namespace Prospect.Launcher Write(offset, data); } - public unsafe void Write(int offset, Span 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