1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-12-01 13:24:25 +01:00

initial import of the updater tool

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40353
This commit is contained in:
David Anderson 2007-03-31 16:23:19 +00:00
parent 3442fd7fe6
commit 32dc2d619f
4 changed files with 545 additions and 0 deletions

92
update_tool/api_link.asm Normal file
View File

@ -0,0 +1,92 @@
;;;;
;; (C)2005-2007 AlliedModders LLC
;; By the Metamod:Source Development Team
;; This software is licensed under the zlib/libpng free software license.
;;
;; This assembly file is a short thunk wrapper to let us load as a VSP and exit quietly,
;; without any overhead of the rest of the interface, and also to prevent linking against
;; tierX or vstdlib
;;;;
;;Exports:
;; void GetBaseDir(char *buffer, maxlength);
;; void *GetThisPointer();
;;Imports:
;; void LoadFunction();
section .text
global GetThisPointer, GetGameDir
global _GetThisPointer, _GetGameDir
extern _LoadFunction
GetThisPointer:
_GetThisPointer:
mov eax, GLOBAL_POINTER
ret
GetGameDir:
_GetGameDir:
push ebp
mov ebp, esp
mov ecx, [engine] ;get this pointer
mov edx, [ecx] ;get the vtable
%ifdef LINUX
push ecx ;push this pointer
%endif
push dword [ebp+12] ;push maxlenth
push dword [ebp+8] ;push buffer
call dword [edx+216] ;call IVEngineServer::GetGameDir
%ifdef LINUX
add esp, 8 ;correct stack
%endif
pop ebp
ret
thisLoadFunction:
push ebp
mov ebp, esp
;get factory
mov eax, [ebp+8]
push dword 0 ;NULL
push dword VENGINESERVER ;iface name
call eax ;call factory
add esp, 8 ;correct stack
test eax, eax ;do we have a valid pointer?
jz .end ;no, bail out
mov [engine], eax ;store the engine pointer
call _LoadFunction
.end:
;We never load, never ever ever!
xor eax, eax
pop ebp
%ifdef LINUX
ret
%else
retn 8
%endif
thisUnloadFunction:
ret
section .data
INTERFACE_NAME DB "ISERVERPLUGINCALLBACKS001", 0
VENGINESERVER DB "VEngineServer021", 0
VIRTUAL_TABLE DD thisLoadFunction
DD thisUnloadFunction
;We don't need any more of the vtable here
GLOBAL_POINTER DD VIRTUAL_TABLE
temp_ret DD 0
temp_ptr DD temp_ret
engine DD 0

View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "update_tool", "update_tool.vcproj", "{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Debug|Win32.ActiveCfg = Debug|Win32
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Debug|Win32.Build.0 = Debug|Win32
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Release|Win32.ActiveCfg = Release|Win32
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="update_tool"
ProjectGUID="{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}"
RootNamespace="update_tool"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="nasmw ..\api_link.asm -f win32 -o ..\obj\api_link.obj -DWIN32"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;UPDATE_TOOL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_STD_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\obj\api_link.obj"
OutputFile="$(OutDir)\sourcemm_update_tool.dll"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="nasmw ..\api_link.asm -f win32 -o ..\obj\api_link.obj -DWIN32"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UPDATE_TOOL_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\obj\api_link.obj"
OutputFile="$(OutDir)\sourcemm_update_tool.dll"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\update_tool.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

230
update_tool/update_tool.cpp Normal file
View File

@ -0,0 +1,230 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
extern "C" void GetGameDir(char *buffer, int maxlength);
extern "C" void *GetThisPointer();
#if defined _MSC_VER
#define SEPCHAR "\\"
#define MMPATH "|gameinfo_path|addons\\metamod\\bin"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#elif defined __linux__
#define SEPCHAR "/"
#define MMPATH "|gameinfo_path|addons/metamod/bin"
#include <unistd.h>
#endif
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
bool s_isspace(char c);
bool RenameFile(const char *old, const char *newf);
/* This will be called by the thunk */
#if defined _MSC_VER
extern "C" void LoadFunction()
#elif defined __linux__
extern "C" void _LoadFunction()
#endif
{
char gamedir[260];
GetGameDir(gamedir, sizeof(gamedir));
char old_path[260];
char new_path[260];
UTIL_Format(old_path, sizeof(old_path), "%s" SEPCHAR "gameinfo.txt", gamedir);
UTIL_Format(new_path, sizeof(new_path), "%s" SEPCHAR "gameinfo.new.txt", gamedir);
FILE *fp = fopen(old_path, "rt");
if (!fp)
{
return;
}
FILE *op = fopen(new_path, "wt");
if (!op)
{
fclose(fp);
return;
}
enum ParseState
{
Parse_None,
Parse_Root,
Parse_GameInfo,
Parse_FileSystem,
Parse_SearchPaths,
};
ParseState ps = Parse_Root;
char input[1024];
char backup[1024];
while (!feof(fp) && fgets(input, sizeof(input), fp) != NULL)
{
UTIL_Format(backup, sizeof(backup), "%s", input);
if (ps != Parse_None)
{
char *inbuf = input;
/* Strip beginning whitespace */
while (*inbuf != '\0' && s_isspace(*inbuf))
{
inbuf++;
}
/* Strip ending whitespace */
size_t len = strlen(inbuf);
for (size_t i = len - 1;
i >= 0 && i < len;
i--)
{
if (s_isspace(inbuf[i]))
{
inbuf[i] = '\0';
len--;
} else {
break;
}
}
/* Strip quotation marks */
if (inbuf[0] == '"'
&& inbuf[len-1] == '"')
{
inbuf[len - 1] = '\0';
inbuf = &inbuf[1];
len -= 2;
}
/* Do tests */
if (ps == Parse_Root && strcmp(inbuf, "GameInfo") == 0)
{
ps = Parse_GameInfo;
} else if (ps == Parse_GameInfo && strcmp(inbuf, "FileSystem") == 0) {
ps = Parse_FileSystem;
} else if (ps == Parse_FileSystem && strcmp(inbuf, "SearchPaths") == 0) {
ps = Parse_SearchPaths;
} else if (ps == Parse_SearchPaths) {
const char *game = strstr(inbuf, "Game");
if (game)
{
if (strstr(game, "GameBin") != NULL
&& strstr(game, MMPATH) != NULL)
{
fclose(op);
op = NULL;
break; /* Nothing more to do! */
} else {
fputs("\t\t\t\tGameBin\t\t" MMPATH "\n", op);
ps = Parse_None;
}
}
}
}
fputs(backup, op);
}
if (!op)
{
/* Well, we can't really do anything else. Give up. */
fclose(fp);
return;
}
/* Close all streams */
fclose(op);
fclose(fp);
/* Move the old file to a backup name */
char backup_name[260];
UTIL_Format(backup_name, sizeof(backup_name), "%s" SEPCHAR "gameinfo.backup.txt", gamedir);
if (!RenameFile(old_path, backup_name))
{
/* If we can't rename, just bail out.
* We don't want to overwrite the client's default
* without backing it up first!
*/
return;
}
if (!RenameFile(new_path, old_path))
{
/* Since this failed, we really have no choice.
* Try and rename the old back.
*/
RenameFile(backup_name, old_path);
return;
}
#if defined _MSC_VER
_unlink(new_path);
#else
unlink(new_path);
#endif
}
bool s_isspace(char c)
{
if ((unsigned)c & 0x80)
{
return false;
} else {
return isspace(c) ? true : false;
}
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
if (len >= maxlength)
{
len = maxlength - 1;
buffer[len] = '\0';
}
return len;
}
bool RenameFile(const char *old, const char *newf)
{
#if defined __linux__
return (rename(old, newf) == 0);
#elif defined WIN32
return (MoveFileA(old, newf) != 0);
#endif
}
#if defined _MSC_VER
extern "C" __declspec(dllexport) void *CreateInterface(const char *iface, int *ret)
#elif defined __linux__
extern "C" __attribute__((visibility("default"))) void *CreateInterface(const char *iface, int *ret)
#endif
{
if (strcmp(iface, "ISERVERPLUGINCALLBACKS001") == 0)
{
if (ret)
{
*ret = 0;
}
return GetThisPointer();
}
if (ret)
{
*ret = 1;
}
return NULL;
}