@@ -27,6 +27,7 @@ SExePatchedStatus GetExePatchedStatus( bool bUseExeCopy )
27
27
status.bDep = UpdatePatchStatusDep ( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
28
28
status.bNvightmare = UpdatePatchStatusNvightmare ( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
29
29
status.bAltModules = UpdatePatchStatusAltModules ( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
30
+ status.bEntryPoint = UpdatePatchStatusEntryPoint ( strGTAEXEPath, PATCH_CHECK ) == PATCH_CHECK_RESULT_ON;
30
31
31
32
return status;
32
33
}
@@ -44,9 +45,10 @@ SExePatchedStatus GetExePatchRequirements( void )
44
45
SExePatchedStatus status;
45
46
status.bTimestamp = GetApplicationSettingInt ( " aero-enabled" ) ? true : false ;
46
47
status.bLargeMem = true ;
47
- status.bDep = true ;
48
+ status.bDep = GetGtaFileVersion ( GetExePathFilename ( false )) != EGtaFileVersion::Encrypted ;
48
49
status.bNvightmare = GetApplicationSettingInt ( " nvhacks" , " optimus-export-enablement" ) ? true : false ;
49
50
status.bAltModules = GetPatchRequirementAltModules ();
51
+ status.bEntryPoint = GetPatchRequirementEntryPoint ();
50
52
51
53
return status;
52
54
}
@@ -70,6 +72,7 @@ bool SetExePatchedStatus( bool bUseExeCopy, const SExePatchedStatus& status )
70
72
bReqAdmin |= UpdatePatchStatusDep ( strGTAEXEPath, status.bDep ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
71
73
bReqAdmin |= UpdatePatchStatusNvightmare ( strGTAEXEPath, status.bNvightmare ? PATCH_SET_ON : PATCH_SET_OFF ) == PATCH_SET_RESULT_REQ_ADMIN;
72
74
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;
73
76
74
77
return !bReqAdmin;
75
78
}
@@ -93,6 +96,9 @@ bool ShouldUseExeCopy( void )
93
96
if ( GetPatchRequirementAltModules () )
94
97
strUseCopyReason += " AltModules" ;
95
98
99
+ if ( GetPatchRequirementEntryPoint () )
100
+ strUseCopyReason += " EntryPoint" ;
101
+
96
102
if ( RequiresAltTabFix () )
97
103
strUseCopyReason += " AltTabFix" ;
98
104
@@ -158,6 +164,8 @@ SString GetPatchExeAdminReason( bool bUseExeCopy, const SExePatchedStatus& reqSt
158
164
return _ (" Update graphics driver compliance" );
159
165
if ( status.bAltModules != reqStatus.bAltModules )
160
166
return _ (" Fix file issues" );
167
+ if ( status.bEntryPoint != reqStatus.bEntryPoint )
168
+ return _ (" Fix file issues" );
161
169
return _ (" Copy main executable to avoid graphic driver issues" );
162
170
}
163
171
@@ -235,20 +243,12 @@ SString GetUsingExePathFilename( void )
235
243
// ////////////////////////////////////////////////////////
236
244
EPatchResult UpdatePatchStatusTimestamp ( const SString& strGTAEXEPath, EPatchMode mode )
237
245
{
246
+ SPEFileOffsets fileOffsets;
247
+ GetPEFileOffsets (fileOffsets, strGTAEXEPath);
248
+
238
249
// Get the top byte of the file link timestamp
239
250
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 );
252
252
253
253
const uchar AERO_DISABLED = 0x42 ;
254
254
const uchar AERO_ENABLED = 0x43 ;
@@ -273,17 +273,10 @@ EPatchResult UpdatePatchStatusTimestamp( const SString& strGTAEXEPath, EPatchMod
273
273
if ( ucTimeStamp != ucTimeStampRequired )
274
274
{
275
275
// 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 ))
279
277
{
280
278
return PATCH_SET_RESULT_REQ_ADMIN;
281
279
}
282
- if ( !fseek ( fh, 0x8B , SEEK_SET ) )
283
- {
284
- fwrite ( &ucTimeStampRequired, sizeof ( ucTimeStampRequired ), 1 , fh );
285
- }
286
- fclose ( fh );
287
280
}
288
281
}
289
282
return PATCH_SET_RESULT_OK;
@@ -299,39 +292,10 @@ EPatchResult UpdatePatchStatusTimestamp( const SString& strGTAEXEPath, EPatchMod
299
292
// ////////////////////////////////////////////////////////
300
293
EPatchResult UpdatePatchStatusLargeMem ( const SString& strGTAEXEPath, EPatchMode mode )
301
294
{
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);
322
297
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 );
335
299
336
300
const ushort LARGEMEM_DISABLED = 0x10f ;
337
301
const ushort LARGEMEM_ENABLED = 0x12f ;
@@ -354,22 +318,15 @@ EPatchResult UpdatePatchStatusLargeMem( const SString& strGTAEXEPath, EPatchMode
354
318
if ( usCharacteristics != usCharacteristicsRequired )
355
319
{
356
320
// 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 ))
360
322
{
361
323
return PATCH_SET_RESULT_REQ_ADMIN;
362
324
}
363
- if ( !fseek ( fh, uiFilePosition, SEEK_SET ) )
364
- {
365
- fwrite ( &usCharacteristicsRequired, sizeof ( usCharacteristicsRequired ), 1 , fh );
366
- }
367
- fclose ( fh );
368
325
}
369
326
}
370
327
else
371
328
{
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 ) );
373
330
}
374
331
return PATCH_SET_RESULT_OK;
375
332
}
@@ -384,53 +341,37 @@ EPatchResult UpdatePatchStatusLargeMem( const SString& strGTAEXEPath, EPatchMode
384
341
// ////////////////////////////////////////////////////////
385
342
EPatchResult UpdatePatchStatusDep ( const SString& strGTAEXEPath, EPatchMode mode )
386
343
{
344
+ SPEFileOffsets fileOffsets;
345
+ GetPEFileOffsets (fileOffsets, strGTAEXEPath);
346
+
387
347
// 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 );
401
350
402
- const ulong DEP_DISABLED = 0x00000002 ;
403
- const ulong DEP_ENABLED = 0x01000002 ;
351
+ const ushort DEP_DISABLED = 0x0000 ;
352
+ const ushort DEP_ENABLED = 0x0100 ;
404
353
405
354
// Return status if just checking
406
355
if ( mode == PATCH_CHECK )
407
356
{
408
- if ( ulDllCharacteristics == DEP_ENABLED )
357
+ if ( usDllCharacteristics == DEP_ENABLED )
409
358
return PATCH_CHECK_RESULT_ON;
410
359
return PATCH_CHECK_RESULT_OFF;
411
360
}
412
361
413
362
// 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 );
415
364
416
365
if ( bCanChangeDepSetting )
417
366
{
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 )
421
369
{
422
370
// 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 ))
426
372
{
427
373
return PATCH_SET_RESULT_REQ_ADMIN;
428
374
}
429
- if ( !fseek ( fh, 0xDC , SEEK_SET ) )
430
- {
431
- fwrite ( &ulDllCharacteristicsRequired, sizeof ( ulDllCharacteristicsRequired ), 1 , fh );
432
- }
433
- fclose ( fh );
434
375
}
435
376
}
436
377
return PATCH_SET_RESULT_OK;
@@ -756,3 +697,81 @@ EPatchResult UpdatePatchStatusAltModules( const SString& strGTAEXEPath, EPatchMo
756
697
757
698
return PATCH_SET_RESULT_OK;
758
699
}
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
+ }
0 commit comments