Skip to content

Commit a05370e

Browse files
committed
Modified launch patcher to work with more exe variants
1 parent f71610e commit a05370e

File tree

5 files changed

+225
-212
lines changed

5 files changed

+225
-212
lines changed

Client/loader/CExePatchedStatus.cpp

Lines changed: 109 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ SExePatchedStatus GetExePatchedStatus( bool bUseExeCopy )
2727
status.bDep = UpdatePatchStatusDep ( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
2828
status.bNvightmare = UpdatePatchStatusNvightmare( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
2929
status.bAltModules = UpdatePatchStatusAltModules( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
30+
status.bEntryPoint = UpdatePatchStatusEntryPoint( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
3031

3132
return status;
3233
}
@@ -44,9 +45,10 @@ SExePatchedStatus GetExePatchRequirements( void )
4445
SExePatchedStatus status;
4546
status.bTimestamp = GetApplicationSettingInt ( "aero-enabled" ) ? true : false;
4647
status.bLargeMem = true;
47-
status.bDep = true;
48+
status.bDep = GetGtaFileVersion(GetExePathFilename(false)) != EGtaFileVersion::Encrypted;
4849
status.bNvightmare = GetApplicationSettingInt( "nvhacks", "optimus-export-enablement" ) ? true : false;
4950
status.bAltModules = GetPatchRequirementAltModules();
51+
status.bEntryPoint = GetPatchRequirementEntryPoint();
5052

5153
return status;
5254
}
@@ -70,6 +72,7 @@ bool SetExePatchedStatus( bool bUseExeCopy, const SExePatchedStatus& status )
7072
bReqAdmin |= UpdatePatchStatusDep ( strGTAEXEPath, status.bDep ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
7173
bReqAdmin |= UpdatePatchStatusNvightmare( strGTAEXEPath, status.bNvightmare ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
7274
bReqAdmin |= UpdatePatchStatusAltModules( strGTAEXEPath, status.bAltModules ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
75+
bReqAdmin |= UpdatePatchStatusEntryPoint( strGTAEXEPath, status.bEntryPoint ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
7376

7477
return !bReqAdmin;
7578
}
@@ -93,6 +96,9 @@ bool ShouldUseExeCopy( void )
9396
if ( GetPatchRequirementAltModules() )
9497
strUseCopyReason += " AltModules";
9598

99+
if ( GetPatchRequirementEntryPoint() )
100+
strUseCopyReason += " EntryPoint";
101+
96102
if ( RequiresAltTabFix() )
97103
strUseCopyReason += " AltTabFix";
98104

@@ -158,6 +164,8 @@ SString GetPatchExeAdminReason( bool bUseExeCopy, const SExePatchedStatus& reqSt
158164
return _("Update graphics driver compliance");
159165
if ( status.bAltModules != reqStatus.bAltModules )
160166
return _("Fix file issues");
167+
if ( status.bEntryPoint != reqStatus.bEntryPoint )
168+
return _("Fix file issues");
161169
return _("Copy main executable to avoid graphic driver issues");
162170
}
163171

@@ -235,20 +243,12 @@ SString GetUsingExePathFilename( void )
235243
//////////////////////////////////////////////////////////
236244
EPatchResult UpdatePatchStatusTimestamp( const SString& strGTAEXEPath, EPatchMode mode )
237245
{
246+
SPEFileOffsets fileOffsets;
247+
GetPEFileOffsets(fileOffsets, strGTAEXEPath);
248+
238249
// Get the top byte of the file link timestamp
239250
uchar ucTimeStamp = 0;
240-
FILE* fh = File::Fopen ( strGTAEXEPath, "rb" );
241-
if ( fh )
242-
{
243-
if ( !fseek ( fh, 0x8B, SEEK_SET ) )
244-
{
245-
if ( fread ( &ucTimeStamp, sizeof ( ucTimeStamp ), 1, fh ) != 1 )
246-
{
247-
ucTimeStamp = 0;
248-
}
249-
}
250-
fclose ( fh );
251-
}
251+
ReadFileValue(strGTAEXEPath, ucTimeStamp, fileOffsets.TimeDateStamp + 3);
252252

253253
const uchar AERO_DISABLED = 0x42;
254254
const uchar AERO_ENABLED = 0x43;
@@ -273,17 +273,10 @@ EPatchResult UpdatePatchStatusTimestamp( const SString& strGTAEXEPath, EPatchMod
273273
if ( ucTimeStamp != ucTimeStampRequired )
274274
{
275275
// Change needed!
276-
SetFileAttributes ( strGTAEXEPath, FILE_ATTRIBUTE_NORMAL );
277-
FILE* fh = File::Fopen ( strGTAEXEPath, "r+b" );
278-
if ( !fh )
276+
if (!WriteFileValue(strGTAEXEPath, ucTimeStampRequired, fileOffsets.TimeDateStamp + 3))
279277
{
280278
return PATCH_SET_RESULT_REQ_ADMIN;
281279
}
282-
if ( !fseek ( fh, 0x8B, SEEK_SET ) )
283-
{
284-
fwrite ( &ucTimeStampRequired, sizeof ( ucTimeStampRequired ), 1, fh );
285-
}
286-
fclose ( fh );
287280
}
288281
}
289282
return PATCH_SET_RESULT_OK;
@@ -299,39 +292,10 @@ EPatchResult UpdatePatchStatusTimestamp( const SString& strGTAEXEPath, EPatchMod
299292
//////////////////////////////////////////////////////////
300293
EPatchResult UpdatePatchStatusLargeMem( const SString& strGTAEXEPath, EPatchMode mode )
301294
{
302-
// Get file position of IMAGE_FILE_HEADER->Characteristics
303-
uint uiFilePosition = 0;
304-
FILE* fh = File::Fopen ( strGTAEXEPath, "rb" );
305-
if ( fh )
306-
{
307-
// 60 is offset of IMAGE_DOS_HEADER->e_lfanew
308-
if ( !fseek ( fh, 60, SEEK_SET ) )
309-
{
310-
long e_lfanew;
311-
if ( fread ( &e_lfanew, sizeof ( e_lfanew ), 1, fh ) == 1 )
312-
{
313-
// 4 is offset of IMAGE_NT_HEADERS->FileHeader
314-
// 18 is offset of IMAGE_FILE_HEADER->Characteristics
315-
uiFilePosition = e_lfanew + 4 + 18;
316-
}
317-
}
318-
fclose ( fh );
319-
}
320-
321-
// Get the value from the header
295+
SPEFileOffsets fileOffsets;
296+
GetPEFileOffsets(fileOffsets, strGTAEXEPath);
322297
ushort usCharacteristics = 0;
323-
fh = File::Fopen ( strGTAEXEPath, "rb" );
324-
if ( fh )
325-
{
326-
if ( !fseek ( fh, uiFilePosition, SEEK_SET ) )
327-
{
328-
if ( fread ( &usCharacteristics, sizeof ( usCharacteristics ), 1, fh ) != 1 )
329-
{
330-
usCharacteristics = 0;
331-
}
332-
}
333-
fclose ( fh );
334-
}
298+
ReadFileValue(strGTAEXEPath, usCharacteristics, fileOffsets.Characteristics);
335299

336300
const ushort LARGEMEM_DISABLED = 0x10f;
337301
const ushort LARGEMEM_ENABLED = 0x12f;
@@ -354,22 +318,15 @@ EPatchResult UpdatePatchStatusLargeMem( const SString& strGTAEXEPath, EPatchMode
354318
if ( usCharacteristics != usCharacteristicsRequired )
355319
{
356320
// Change needed!
357-
SetFileAttributes ( strGTAEXEPath, FILE_ATTRIBUTE_NORMAL );
358-
FILE* fh = File::Fopen ( strGTAEXEPath, "r+b" );
359-
if ( !fh )
321+
if (!WriteFileValue(strGTAEXEPath, usCharacteristicsRequired, fileOffsets.Characteristics))
360322
{
361323
return PATCH_SET_RESULT_REQ_ADMIN;
362324
}
363-
if ( !fseek ( fh, uiFilePosition, SEEK_SET ) )
364-
{
365-
fwrite ( &usCharacteristicsRequired, sizeof ( usCharacteristicsRequired ), 1, fh );
366-
}
367-
fclose ( fh );
368325
}
369326
}
370327
else
371328
{
372-
WriteDebugEventAndReport ( 9805, SString ( "Unable to set LARGE_ADDRESS_AWARE [FilePosition=0x%x Characteristics=0x%x]", uiFilePosition, usCharacteristics ) );
329+
WriteDebugEventAndReport ( 9805, SString ( "Unable to set LARGE_ADDRESS_AWARE [FilePosition=0x%x Characteristics=0x%x]", fileOffsets.Characteristics, usCharacteristics ) );
373330
}
374331
return PATCH_SET_RESULT_OK;
375332
}
@@ -384,53 +341,37 @@ EPatchResult UpdatePatchStatusLargeMem( const SString& strGTAEXEPath, EPatchMode
384341
//////////////////////////////////////////////////////////
385342
EPatchResult UpdatePatchStatusDep( const SString& strGTAEXEPath, EPatchMode mode )
386343
{
344+
SPEFileOffsets fileOffsets;
345+
GetPEFileOffsets(fileOffsets, strGTAEXEPath);
346+
387347
// Get the value from the header
388-
ulong ulDllCharacteristics = 0;
389-
FILE* fh = File::Fopen ( strGTAEXEPath, "rb" );
390-
if ( fh )
391-
{
392-
if ( !fseek ( fh, 0xDC, SEEK_SET ) )
393-
{
394-
if ( fread ( &ulDllCharacteristics, sizeof ( ulDllCharacteristics ), 1, fh ) != 1 )
395-
{
396-
ulDllCharacteristics = 0;
397-
}
398-
}
399-
fclose ( fh );
400-
}
348+
ushort usDllCharacteristics = 0;
349+
ReadFileValue(strGTAEXEPath, usDllCharacteristics, fileOffsets.DllCharacteristics);
401350

402-
const ulong DEP_DISABLED = 0x00000002;
403-
const ulong DEP_ENABLED = 0x01000002;
351+
const ushort DEP_DISABLED = 0x0000;
352+
const ushort DEP_ENABLED = 0x0100;
404353

405354
// Return status if just checking
406355
if ( mode == PATCH_CHECK )
407356
{
408-
if ( ulDllCharacteristics == DEP_ENABLED )
357+
if ( usDllCharacteristics == DEP_ENABLED )
409358
return PATCH_CHECK_RESULT_ON;
410359
return PATCH_CHECK_RESULT_OFF;
411360
}
412361

413362
// Check it's a value we're expecting
414-
bool bCanChangeDepSetting = ( ulDllCharacteristics == DEP_DISABLED || ulDllCharacteristics == DEP_ENABLED );
363+
bool bCanChangeDepSetting = ( usDllCharacteristics == DEP_DISABLED || usDllCharacteristics == DEP_ENABLED );
415364

416365
if ( bCanChangeDepSetting )
417366
{
418-
ulong ulDllCharacteristicsRequired = ( mode == PATCH_SET_ON ) ? DEP_ENABLED : DEP_DISABLED;
419-
dassert( ulDllCharacteristicsRequired == DEP_ENABLED );
420-
if ( ulDllCharacteristics != ulDllCharacteristicsRequired )
367+
ushort usDllCharacteristicsRequired = ( mode == PATCH_SET_ON ) ? DEP_ENABLED : DEP_DISABLED;
368+
if ( usDllCharacteristics != usDllCharacteristicsRequired )
421369
{
422370
// Change needed!
423-
SetFileAttributes ( strGTAEXEPath, FILE_ATTRIBUTE_NORMAL );
424-
FILE* fh = File::Fopen ( strGTAEXEPath, "r+b" );
425-
if ( !fh )
371+
if (!WriteFileValue(strGTAEXEPath, usDllCharacteristicsRequired, fileOffsets.DllCharacteristics))
426372
{
427373
return PATCH_SET_RESULT_REQ_ADMIN;
428374
}
429-
if ( !fseek ( fh, 0xDC, SEEK_SET ) )
430-
{
431-
fwrite ( &ulDllCharacteristicsRequired, sizeof ( ulDllCharacteristicsRequired ), 1, fh );
432-
}
433-
fclose ( fh );
434375
}
435376
}
436377
return PATCH_SET_RESULT_OK;
@@ -756,3 +697,81 @@ EPatchResult UpdatePatchStatusAltModules( const SString& strGTAEXEPath, EPatchMo
756697

757698
return PATCH_SET_RESULT_OK;
758699
}
700+
701+
702+
//////////////////////////////////////////////////////////
703+
//
704+
// UpdatePatchStatusEntryPoint
705+
//
706+
// Fix AddressOfEntryPoint incase of corruption
707+
//
708+
//////////////////////////////////////////////////////////
709+
EPatchResult UpdatePatchStatusEntryPoint(const SString& strGTAEXEPath, EPatchMode mode)
710+
{
711+
SPEFileOffsets fileOffsets;
712+
GetPEFileOffsets(fileOffsets, strGTAEXEPath);
713+
714+
// Get address from the file
715+
uint uiCurrentEntryPoint = 0;
716+
ReadFileValue(strGTAEXEPath, uiCurrentEntryPoint, fileOffsets.AddressOfEntryPoint);
717+
718+
// Calc required address
719+
std::map<EGtaFileVersion, uint> versionEntryPoints = {{EGtaFileVersion::US, 0x0424570}, {EGtaFileVersion::EU, 0x04245B0}, {EGtaFileVersion::Encrypted, 0x0EFFE40}};
720+
uint uiRequiredEntryPoint = MapFindRef(versionEntryPoints, GetGtaFileVersion(strGTAEXEPath));
721+
722+
if (mode == PATCH_CHECK)
723+
{
724+
if (uiCurrentEntryPoint == uiRequiredEntryPoint)
725+
return PATCH_CHECK_RESULT_ON;
726+
return PATCH_CHECK_RESULT_OFF;
727+
}
728+
729+
// Check it's a value that should be fixed
730+
bool bCanChangeEntryPoint = (uiCurrentEntryPoint > 0x1170000) || (uiCurrentEntryPoint == uiRequiredEntryPoint);
731+
if (bCanChangeEntryPoint)
732+
{
733+
if (mode == PATCH_SET_ON && uiCurrentEntryPoint != uiRequiredEntryPoint)
734+
{
735+
// Change needed! Can't do this to gta_sa.exe
736+
assert(!strGTAEXEPath.EndsWithI("gta_sa.exe"));
737+
if (!WriteFileValue(strGTAEXEPath, uiRequiredEntryPoint, fileOffsets.AddressOfEntryPoint))
738+
{
739+
return PATCH_SET_RESULT_REQ_ADMIN;
740+
}
741+
}
742+
}
743+
else
744+
{
745+
WriteDebugEventAndReport(9806, SString ("Unable to set AddressOfEntryPoint [FilePosition=0x%x EntryPoint=0x%x]", fileOffsets.AddressOfEntryPoint, uiCurrentEntryPoint));
746+
}
747+
return PATCH_SET_RESULT_OK;
748+
}
749+
750+
751+
//////////////////////////////////////////////////////////
752+
//
753+
// GetPatchRequirementEntryPoint
754+
//
755+
// Return true if AddressOfEntryPoint in gta_sa.exe should be fixed (in proxy_sa.exe)
756+
//
757+
//////////////////////////////////////////////////////////
758+
bool GetPatchRequirementEntryPoint( void )
759+
{
760+
// Only do file check once per launch
761+
static bool bDone = false;
762+
static bool bMismatch = false;
763+
764+
if (!bDone)
765+
{
766+
SString strGTAExePath = GetExePathFilename(false);
767+
if ( !strGTAExePath.empty() )
768+
{
769+
bMismatch = (UpdatePatchStatusEntryPoint(strGTAExePath, PATCH_CHECK) == PATCH_CHECK_RESULT_OFF);
770+
}
771+
bDone = true;
772+
773+
if (bMismatch)
774+
WriteDebugEvent("PatchRequirementEntryPoint: Need to change entry point");
775+
}
776+
return bMismatch;
777+
}

Client/loader/CExePatchedStatus.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct SExePatchedStatus
1515
bool bDep;
1616
bool bNvightmare;
1717
bool bAltModules;
18+
bool bEntryPoint;
1819

1920
bool operator!= ( const SExePatchedStatus& other ) const { return !operator==( other ); }
2021
bool operator== ( const SExePatchedStatus& other ) const
@@ -23,7 +24,8 @@ struct SExePatchedStatus
2324
&& bLargeMem == other.bLargeMem
2425
&& bDep == other.bDep
2526
&& bNvightmare == other.bNvightmare
26-
&& bAltModules == other.bAltModules;
27+
&& bAltModules == other.bAltModules
28+
&& bEntryPoint == other.bEntryPoint;
2729
}
2830
};
2931

@@ -59,3 +61,5 @@ EPatchResult UpdatePatchStatusLargeMem ( const SString& strGTAEXEPa
5961
EPatchResult UpdatePatchStatusDep ( const SString& strGTAEXEPath, EPatchMode mode );
6062
bool GetPatchRequirementAltModules ( void );
6163
EPatchResult UpdatePatchStatusAltModules ( const SString& strGTAEXEPath, EPatchMode mode );
64+
bool GetPatchRequirementEntryPoint ( void );
65+
EPatchResult UpdatePatchStatusEntryPoint ( const SString& strGTAEXEPath, EPatchMode mode );

Client/loader/StdInc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
#include <stdio.h>
1212
#include "shellapi.h"
1313
#include <Wscapi.h>
14-
1514
#include <shlobj.h>
1615
#include <Psapi.h>
1716
#include <time.h>
17+
#include <fstream>
1818

1919
#include "..\sdk\core\CLocalizationInterface.h"
2020
extern CLocalizationInterface* g_pLocalization;

0 commit comments

Comments
 (0)