CEngineAPI::SetStartupInfo rebuild

Full rebuild of assembled function "CEngineAPI::SetStartupInfo". The assembly seems to match original function after rebuild. Does NOT support S1 yet, because TRACEINIT is inline in S1.
This commit is contained in:
Kawe Mazidjatari 2022-11-07 22:25:20 +01:00
parent 7be85c03a7
commit 6266549cd7
14 changed files with 178 additions and 22 deletions

View File

@ -12,9 +12,9 @@
struct StartupInfo_t
{
void* m_pInstance;
const char m_pBaseDirectory[260];
const char m_pInitialMod[260];
const char m_pInitialGame[260];
const char m_szBaseDirectory[260];
const char m_szInitialMod[260];
const char m_szInitialGame[260];
uint8_t m_pParentAppSystemGroup[236];
bool m_bTextMode;
};

View File

@ -69,6 +69,7 @@
#include "engine/client/cl_main.h"
#include "engine/client/client.h"
#include "engine/client/clientstate.h"
#include "engine/traceinit.h"
#include "engine/common.h"
#include "engine/cmodel_bsp.h"
#include "engine/host.h"

View File

@ -1,6 +1,9 @@
#pragma once
/* ==== COMMON ========================================================================================================================================================== */
inline CMemory p_COM_InitFilesystem;
inline auto COM_InitFilesystem = p_COM_InitFilesystem.RCast<void* (*)(const char* pFullModPath)>();
inline CMemory p_COM_ExplainDisconnection;
inline auto COM_ExplainDisconnection = p_COM_ExplainDisconnection.RCast<void* (*)(uint64_t level, const char* fmt, ...)>();
@ -9,12 +12,16 @@ class VCommon : public IDetour
{
virtual void GetAdr(void) const
{
spdlog::debug("| FUN: COM_InitFilesystem : {:#18x} |\n", p_COM_InitFilesystem.GetPtr());
spdlog::debug("| FUN: COM_ExplainDisconnection : {:#18x} |\n", p_COM_ExplainDisconnection.GetPtr());
spdlog::debug("+----------------------------------------------------------------+\n");
}
virtual void GetFun(void) const
{
p_COM_InitFilesystem = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xF9\x48\xC7\x44\x24\x00\x00\x00\x00\x00"), "xxxx?xxxx?xxxx????xxxxxxx?????");
p_COM_ExplainDisconnection = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x8B\xC4\x48\x89\x50\x10\x4C\x89\x40\x18\x4C\x89\x48\x20\x48\x81\xEC\x00\x00\x00\x00"), "xxxxxxxxxxxxxxxxxx????");
COM_InitFilesystem = p_COM_InitFilesystem.RCast<void* (*)(const char*)>(); /*48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 48 C7 44 24 ?? ?? ?? ?? ??*/
COM_ExplainDisconnection = p_COM_ExplainDisconnection.RCast<void* (*)(uint64_t, const char*, ...)>(); /*48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 48 81 EC ?? ?? ?? ??*/
}
virtual void GetVar(void) const { }

View File

@ -6,14 +6,18 @@
//===========================================================================//
#include "core/stdafx.h"
#include "tier0/commandline.h"
#include "tier1/cmd.h"
#include "tier1/cvar.h"
#include "tier1/strtools.h"
#include "engine/sys_dll.h"
#include "engine/sys_dll2.h"
#include "engine/host_cmd.h"
#include "engine/traceinit.h"
#ifndef DEDICATED
#include "client/vengineclient_impl.h"
#endif // !DEDICATED
#include "filesystem/filesystem.h"
//-----------------------------------------------------------------------------
// Figure out if we're running a Valve mod or not.
@ -41,7 +45,7 @@ static bool IsRespawnMod(const char* pModName)
//-----------------------------------------------------------------------------
// Initialization, shutdown of a mod.
//-----------------------------------------------------------------------------
bool CEngineAPI::ModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir)
bool CEngineAPI::VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir)
{
g_pConCommand->InitShipped();
g_pConCommand->PurgeShipped();
@ -59,13 +63,77 @@ bool CEngineAPI::ModInit(CEngineAPI* pEngineAPI, const char* pModName, const cha
return results;
}
//-----------------------------------------------------------------------------
// Sets startup info
//-----------------------------------------------------------------------------
void CEngineAPI::VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo)
{
char szCacheEnableFilePath[280]; // [rsp+20h] [rbp-118h] BYREF
if (*g_bTextMode)
{
return;
}
strncpy(&*g_szBaseDir, pStartupInfo->m_szBaseDirectory, 260);
g_pEngineParms->baseDirectory = &*g_szBaseDir;
void** v4 = &pEngineAPI->m_StartupInfo.m_pInstance;
size_t nInstances = 6;
g_szBaseDir[259] = '\0';
do
{
v4 += 16;
uint64_t v6 = *(_QWORD*)&pStartupInfo->m_pInstance;
pStartupInfo = (StartupInfo_t*)((char*)pStartupInfo + 128);
*((_QWORD*)v4 - 8) = v6;
*((_QWORD*)v4 - 7) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[132];
*((_QWORD*)v4 - 6) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[148];
*((_QWORD*)v4 - 5) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[164];
*((_QWORD*)v4 - 4) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[180];
*((_QWORD*)v4 - 3) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[196];
*((_QWORD*)v4 - 2) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[212];
*((_QWORD*)v4 - 1) = *(_QWORD*)&pStartupInfo[-1].m_pParentAppSystemGroup[228];
--nInstances;
} while (nInstances);
*(_QWORD*)v4 = *(_QWORD*)&pStartupInfo->m_pInstance;
*((_QWORD*)v4 + 1) = *(_QWORD*)&pStartupInfo->m_szBaseDirectory[8];
char bFixSlashes = FileSystem()->GetCurrentDirectory(szCacheEnableFilePath, 260) ? szCacheEnableFilePath[0] : '\0';
size_t nCachePathLen = strlen(szCacheEnableFilePath);
size_t nCacheFileLen = 15; // sizeof '/vpk/enable.txt' - 1;
if ((nCachePathLen + nCacheFileLen) < 0x104 || (nCacheFileLen = 259 - nCachePathLen, nCachePathLen != 259))
{
strncat(szCacheEnableFilePath, "/vpk/enable.txt", nCacheFileLen)[259] = '\0';
bFixSlashes = szCacheEnableFilePath[0];
}
if (bFixSlashes)
{
V_FixSlashes(szCacheEnableFilePath, '/');
}
if (FileSystem()->FileExists(szCacheEnableFilePath, nullptr))
{
FileSystem()->SetVPKCacheModeClient();
FileSystem()->AddSearchPath(".", "MAIN", SearchPathAdd_t::PATH_ADD_TO_TAIL);
FileSystem()->MountVPKFile("vpk/client_frontend.bsp");
}
v_TRACEINIT(NULL, "COM_InitFilesystem( m_StartupInfo.m_szInitialMod )", "COM_ShutdownFileSystem()");
COM_InitFilesystem(pEngineAPI->m_StartupInfo.m_szInitialMod);
*g_bTextMode = true;
}
///////////////////////////////////////////////////////////////////////////////
void SysDll2_Attach()
{
DetourAttach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::ModInit);
DetourAttach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::VModInit);
DetourAttach((LPVOID*)&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo);
}
void SysDll2_Detach()
{
DetourDetach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::ModInit);
DetourDetach((LPVOID*)&CEngineAPI_ModInit, &CEngineAPI::VModInit);
DetourDetach((LPVOID*)&v_CEngineAPI_SetStartupInfo, &CEngineAPI::VSetStartupInfo);
}

View File

@ -31,8 +31,9 @@ public:
virtual void SetMap(const char* pMapName) = 0;
static bool ModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir);
private:
static bool VModInit(CEngineAPI* pEngineAPI, const char* pModName, const char* pGameDir);
static void VSetStartupInfo(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo);
//private:
void* m_hEditorHWnd;
bool m_bRunningSimulation;
StartupInfo_t m_StartupInfo;
@ -47,14 +48,19 @@ inline auto CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast<bool (*)(CEngineAPI*
inline CMemory p_CEngineAPI_MainLoop;
inline auto CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast<bool(*)(void)>();
inline CMemory p_PakFile_Init;
inline auto PakFile_Init = p_PakFile_Init.RCast<void (*)(char* buffer, char* source, char vpk_file)>();
inline CMemory p_CEngineAPI_SetStartupInfo;
inline auto v_CEngineAPI_SetStartupInfo = p_CEngineAPI_SetStartupInfo.RCast<void (*)(CEngineAPI* pEngineAPI, StartupInfo_t* pStartupInfo)>();
inline CMemory p_ResetMTVFTaskItem;
inline auto v_ResetMTVFTaskItem = p_ResetMTVFTaskItem.RCast<void*(*)(void)>();
inline int64_t* g_pMTVFTaskItem; // struct.
inline char* g_szMTVFItemName;
inline CMemory p_PakFile_Init;
inline auto PakFile_Init = p_PakFile_Init.RCast<void (*)(char* buffer, char* source, char vpk_file)>();
inline bool* g_bTextMode = nullptr;
inline char* g_szBaseDir = nullptr; // static size = 260
inline int64_t* g_pMTVFTaskItem = nullptr; // struct.
inline char* g_szMTVFItemName = nullptr;
void SysDll2_Attach();
@ -67,8 +73,13 @@ class VSys_Dll2 : public IDetour
spdlog::debug("| FUN: CEngineAPI::Connect : {:#18x} |\n", p_CEngineAPI_Connect.GetPtr());
spdlog::debug("| FUN: CEngineAPI::ModInit : {:#18x} |\n", p_CEngineAPI_ModInit.GetPtr());
spdlog::debug("| FUN: CEngineAPI::MainLoop : {:#18x} |\n", p_CEngineAPI_MainLoop.GetPtr());
spdlog::debug("| FUN: PakFile_Init : {:#18x} |\n", p_PakFile_Init.GetPtr());
#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
spdlog::debug("| FUN: CEngineAPI::SetStartupInfo : {:#18x} |\n", p_CEngineAPI_SetStartupInfo.GetPtr());
#endif
spdlog::debug("| FUN: ResetMTVFTaskItem : {:#18x} |\n", p_ResetMTVFTaskItem.GetPtr());
spdlog::debug("| FUN: PakFile_Init : {:#18x} |\n", p_PakFile_Init.GetPtr());
spdlog::debug("| VAR: g_bTextMode : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_bTextMode));
spdlog::debug("| VAR: g_szBaseDir : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_szBaseDir));
spdlog::debug("| VAR: g_pMTVFTaskItem : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_pMTVFTaskItem));
spdlog::debug("| VAR: g_szMTVFItemName : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_szMTVFItemName));
spdlog::debug("+----------------------------------------------------------------+\n");
@ -85,16 +96,21 @@ class VSys_Dll2 : public IDetour
p_CEngineAPI_MainLoop = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\xE8\x00\x00\x00\x00\x48\x8B\x15\x00\x00\x00\x00\x84\xC0\xB9\x00\x00\x00\x00"), "x????xxx????xxx????").FollowNearCallSelf();
p_PakFile_Init = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x44\x88\x44\x24\x00\x53\x55\x56\x57"), "xxxx?xxxx");
#endif
p_CEngineAPI_SetStartupInfo = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x48\x8B\xDA"), "xxxx??xxx????xx?????xxx");
p_ResetMTVFTaskItem = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x83\xEC\x28\x48\x8B\x15\x00\x00\x00\x00\x48\x85\xD2\x0F\x84\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x33\xC9\xE8\x00\x00\x00\x00\x0F\x28\x05\x00\x00\x00\x00\x0F\x28\x0D\x00\x00\x00\x00\x0F\x11\x05\x00\x00\x00\x00\x0F\x28\x05\x00\x00\x00\x00\x0F\x11\x0D\x00\x00\x00\x00\x0F\x28\x0D\x00\x00\x00\x00\x0F\x11\x05\x00\x00\x00\x00\x0F\x11\x0D\x00\x00\x00\x00\x48\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00"),
"xxxxxxx????xxxxx????xxx????xxxxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????xxx????????xx????");
CEngineAPI_Connect = p_CEngineAPI_Connect.RCast<bool (*)(CEngineAPI*, CreateInterfaceFn)>(); /*48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15 ?? ?? ?? ??*/
CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast<bool (*)(CEngineAPI*, const char*, const char*)>(); /*48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8*/
CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast<bool(*)(void)>(); /*E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??*/
PakFile_Init = p_PakFile_Init.RCast<void (*)(char*, char*, char)>(); /*44 88 44 24 ?? 53 55 56 57*/
CEngineAPI_Connect = p_CEngineAPI_Connect.RCast<bool (*)(CEngineAPI*, CreateInterfaceFn)>(); /*48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 89 15 ?? ?? ?? ??*/
CEngineAPI_ModInit = p_CEngineAPI_ModInit.RCast<bool (*)(CEngineAPI*, const char*, const char*)>(); /*48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 4D 8B F8*/
CEngineAPI_MainLoop = p_CEngineAPI_MainLoop.RCast<bool(*)(void)>(); /*E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 84 C0 B9 ?? ?? ?? ??*/
v_CEngineAPI_SetStartupInfo = p_CEngineAPI_SetStartupInfo.RCast<void (*)(CEngineAPI*, StartupInfo_t*)>(); /*48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 48 8B DA*/
PakFile_Init = p_PakFile_Init.RCast<void (*)(char*, char*, char)>(); /*44 88 44 24 ?? 53 55 56 57*/
}
virtual void GetVar(void) const
{
g_bTextMode = p_CEngineAPI_SetStartupInfo.FindPattern("80 3D", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
g_szBaseDir = p_CEngineAPI_SetStartupInfo.FindPattern("48 8D", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
g_pMTVFTaskItem = p_ResetMTVFTaskItem.FindPattern("48 8B", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x3, 0x7).RCast<int64_t*>();
g_szMTVFItemName = p_ResetMTVFTaskItem.FindPattern("C6 05", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x2, 0x7).RCast<char*>();
}

29
r5dev/engine/traceinit.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef TRACEINIT_H
#define TRACEINIT_H
inline CMemory p_TRACEINIT;
inline auto v_TRACEINIT = p_TRACEINIT.RCast<void(*)(void* undef, const char* initfunc, const char* shutdownfunc)>();
///////////////////////////////////////////////////////////////////////////////
class VTraceInit : public IDetour
{
virtual void GetAdr(void) const
{
spdlog::debug("| FUN: TRACEINIT : {:#18x} |\n", p_TRACEINIT.GetPtr());
spdlog::debug("+----------------------------------------------------------------+\n");
}
virtual void GetFun(void) const
{
p_TRACEINIT = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x00\x49\x8B\xF8\x48\x8B\xF2\x48\x85\xC0"), "xxxx?xxxx?xxxxxxxx????xxxxxxxxx");
v_TRACEINIT = p_TRACEINIT.RCast<void (*)(void*, const char*, const char*)>(); /*48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B 05 ? ? ? ? 49 8B F8 48 8B F2 48 85 C0*/
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }
virtual void Attach(void) const { }
virtual void Detach(void) const { }
};
///////////////////////////////////////////////////////////////////////////////
REGISTER(VTraceInit);
#endif // TRACEINIT_H

View File

@ -1,4 +1,5 @@
#include "core/stdafx.h"
#include "tier1/strtools.h"
FORCEINLINE unsigned char tolower_fast(unsigned char c)
{
@ -85,9 +86,7 @@ int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes)
{
if (cubDestSizeInBytes > 0)
{
pUTF8[0] = 0;
}
#ifdef _WIN32
int cchResult = WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL);
@ -98,9 +97,24 @@ int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes
#endif
if (cubDestSizeInBytes > 0)
{
pUTF8[cubDestSizeInBytes - 1] = 0;
}
return cchResult;
}
//-----------------------------------------------------------------------------
// Purpose: Changes all '/' or '\' characters into separator
// Input : *pName -
// cSeparator -
//-----------------------------------------------------------------------------
void V_FixSlashes(char* pName, char cSeperator /* = CORRECT_PATH_SEPARATOR */)
{
while (*pName)
{
if (*pName == INCORRECT_PATH_SEPARATOR || *pName == CORRECT_PATH_SEPARATOR)
{
*pName = cSeperator;
}
pName++;
}
}

View File

@ -1,5 +1,13 @@
#pragma once
#ifdef _WIN32
#define CORRECT_PATH_SEPARATOR '\\'
#define INCORRECT_PATH_SEPARATOR '/'
#elif POSIX
#define CORRECT_PATH_SEPARATOR '/'
#define INCORRECT_PATH_SEPARATOR '\\'
#endif
#define V_snprintf snprintf
#define V_strlower _strlwr
#define V_strlen strlen
@ -21,4 +29,5 @@
char const* V_stristr(char const* pStr, char const* pSearch);
int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes);
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes);
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes);
void V_FixSlashes(char* pname, char separator = CORRECT_PATH_SEPARATOR);

View File

@ -202,6 +202,7 @@
<ClInclude Include="..\engine\sys_getmodes.h" />
<ClInclude Include="..\engine\sys_mainwind.h" />
<ClInclude Include="..\engine\sys_utils.h" />
<ClInclude Include="..\engine\traceinit.h" />
<ClInclude Include="..\filesystem\basefilesystem.h" />
<ClInclude Include="..\filesystem\filesystem.h" />
<ClInclude Include="..\gameui\IConsole.h" />

View File

@ -1796,6 +1796,9 @@
<ClInclude Include="..\engine\gl_rmain.h">
<Filter>sdk\engine</Filter>
</ClInclude>
<ClInclude Include="..\engine\traceinit.h">
<Filter>sdk\engine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\shared\resource\lockedserver.png">

View File

@ -170,6 +170,7 @@
<ClInclude Include="..\engine\sys_engine.h" />
<ClInclude Include="..\engine\sys_getmodes.h" />
<ClInclude Include="..\engine\sys_utils.h" />
<ClInclude Include="..\engine\traceinit.h" />
<ClInclude Include="..\filesystem\basefilesystem.h" />
<ClInclude Include="..\filesystem\filesystem.h" />
<ClInclude Include="..\game\server\ai_network.h" />

View File

@ -1251,6 +1251,9 @@
<ClInclude Include="..\public\server_class.h">
<Filter>sdk\public</Filter>
</ClInclude>
<ClInclude Include="..\engine\traceinit.h">
<Filter>sdk\engine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\opcodes.cpp">

View File

@ -216,6 +216,7 @@
<ClInclude Include="..\engine\sys_getmodes.h" />
<ClInclude Include="..\engine\sys_mainwind.h" />
<ClInclude Include="..\engine\sys_utils.h" />
<ClInclude Include="..\engine\traceinit.h" />
<ClInclude Include="..\filesystem\basefilesystem.h" />
<ClInclude Include="..\filesystem\filesystem.h" />
<ClInclude Include="..\gameui\IConsole.h" />

View File

@ -1892,6 +1892,9 @@
<ClInclude Include="..\public\server_class.h">
<Filter>sdk\public</Filter>
</ClInclude>
<ClInclude Include="..\engine\traceinit.h">
<Filter>sdk\engine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\shared\resource\lockedserver.png">