@@ -579,7 +579,8 @@ namespace
579579 DWORD valueType = REG_SZ;
580580 DWORD valueSize = 0 ;
581581 LONG result = RegQueryValueExW (hKey, wstrValueName.c_str (), nullptr , &valueType, nullptr , &valueSize);
582- if (result != ERROR_SUCCESS || (valueType != REG_SZ && valueType != REG_EXPAND_SZ) || valueSize == 0 || valueSize > kMaxRegistryValueBytes )
582+ if (result != ERROR_SUCCESS || (valueType != REG_SZ && valueType != REG_EXPAND_SZ) || valueSize == 0 || valueSize > kMaxRegistryValueBytes ||
583+ (valueSize % sizeof (wchar_t )) != 0 )
583584 {
584585 RegCloseKey (hKey);
585586 return " " ;
@@ -589,13 +590,11 @@ namespace
589590 result = RegQueryValueExW (hKey, wstrValueName.c_str (), nullptr , &valueType, reinterpret_cast <LPBYTE>(buffer.data ()), &valueSize);
590591 RegCloseKey (hKey);
591592
592- if (result != ERROR_SUCCESS || (valueType != REG_SZ && valueType != REG_EXPAND_SZ) || valueSize > kMaxRegistryValueBytes )
593+ if (result != ERROR_SUCCESS || (valueType != REG_SZ && valueType != REG_EXPAND_SZ) || valueSize > kMaxRegistryValueBytes ||
594+ (valueSize % sizeof (wchar_t )) != 0 )
593595 return " " ;
594596
595- if (valueSize >= sizeof (wchar_t ))
596- buffer[(valueSize / sizeof (wchar_t )) - 1u ] = L' \0 ' ;
597- else
598- buffer[0 ] = L' \0 ' ;
597+ buffer[valueSize / sizeof (wchar_t )] = L' \0 ' ;
599598
600599 // Expand environment variable references for REG_EXPAND_SZ values so callers see a real
601600 // filesystem path. Without this, a value like "%ProgramFiles%\..." would fail validation.
@@ -620,7 +619,7 @@ namespace
620619SString GetInstallPathForLauncher ()
621620{
622621 const SString strLaunchPath = GetLaunchPath ();
623- if (!IsTemporaryUpdateLaunchPath (strLaunchPath))
622+ if (!SharedUtil:: IsTemporaryUpdateLaunchPath (strLaunchPath))
624623 return strLaunchPath;
625624
626625 // Prefer the resolved base dir over the registry when one was already established. In the
@@ -633,7 +632,7 @@ SString GetInstallPathForLauncher()
633632 // back into GetInstallPathForLauncher() and would recurse for any temp launcher whose g_strMTASAPath
634633 // has not yet been populated by the far-update sequencer path. Empty string falls through to the
635634 // per-view registry loop below, preserving the temp-launcher-without-far-update fallback.
636- if (!g_strMTASAPath.empty () && IsUsableMtasaInstallRoot (g_strMTASAPath) && !IsTemporaryUpdateLaunchPath (g_strMTASAPath) &&
635+ if (!g_strMTASAPath.empty () && SharedUtil:: IsUsableMtasaInstallRoot (g_strMTASAPath) && !SharedUtil:: IsTemporaryUpdateLaunchPath (g_strMTASAPath) &&
637636 !g_strMTASAPath.CompareI (strLaunchPath))
638637 return g_strMTASAPath;
639638
@@ -651,7 +650,7 @@ SString GetInstallPathForLauncher()
651650 for (int i = 0 ; i < viewCount; ++i)
652651 {
653652 const SString strSavedInstallPath = ReadInstallRootRegistryView (viewFlags[i]);
654- if (IsUsableMtasaInstallRoot (strSavedInstallPath) && !IsTemporaryUpdateLaunchPath (strSavedInstallPath))
653+ if (SharedUtil:: IsUsableMtasaInstallRoot (strSavedInstallPath) && !SharedUtil:: IsTemporaryUpdateLaunchPath (strSavedInstallPath))
655654 return strSavedInstallPath;
656655 }
657656
@@ -661,30 +660,6 @@ SString GetInstallPathForLauncher()
661660 return SString ();
662661}
663662
664- bool IsUsableMtasaInstallRoot (const SString& strPath)
665- {
666- if (strPath.empty ())
667- return false ;
668-
669- return FileExists (PathJoin (strPath, " Multi Theft Auto.exe" )) || FileExists (PathJoin (strPath, " Multi Theft Auto_d.exe" )) ||
670- FileExists (PathJoin (strPath, " mta" , " core.dll" )) || FileExists (PathJoin (strPath, " MTA" , " core.dll" )) ||
671- FileExists (PathJoin (strPath, " mta" , " core_d.dll" )) || FileExists (PathJoin (strPath, " MTA" , " core_d.dll" ));
672- }
673-
674- bool IsTemporaryUpdateLaunchPath (const SString& strLaunchPath)
675- {
676- if (strLaunchPath.empty ())
677- return false ;
678-
679- if (!strLaunchPath.ContainsI (" \\ upcache\\ " ))
680- return false ;
681-
682- // The auto-update flow creates the extraction directory in Install.cpp::CheckOnRestartCommand
683- // as MakeUniquePath("...\\upcache\\_<archiveName>_tmp_"), so the leaf always begins with '_'.
684- const SString strLeaf = ExtractFilename (strLaunchPath);
685- return strLeaf.BeginsWith (" _" ) && strLeaf.ContainsI (" _tmp_" );
686- }
687-
688663void SetMTASAPathSource (bool bReadFromRegistry)
689664{
690665 if (bReadFromRegistry)
@@ -718,7 +693,7 @@ void SetMTASAPathSource(bool bReadFromRegistry)
718693 // values. A temp launcher started without the far-update sequencer state would otherwise
719694 // contaminate Last Run Location with an upcache\_*_tmp_* path that gets deleted later by
720695 // CleanDownloadCache, leaving a stale registry pointer that produces U01 on the next launch.
721- if (IsTemporaryUpdateLaunchPath (strLaunchPath))
696+ if (SharedUtil:: IsTemporaryUpdateLaunchPath (strLaunchPath))
722697 {
723698 AddReportLog (1063 , SString (" SetMTASAPathSource: refusing to record temp launch path '%s' in registry" , strLaunchPath.c_str ()));
724699 g_strMTASAPath = strLaunchPath;
@@ -1391,7 +1366,7 @@ void UpdateMTAVersionApplicationSetting(bool bQuiet)
13911366 bool bFreeModule = false ;
13921367
13931368 const SString strInstallPath = GetInstallPathForLauncher ();
1394- if (IsUsableMtasaInstallRoot (strInstallPath))
1369+ if (SharedUtil:: IsUsableMtasaInstallRoot (strInstallPath))
13951370 {
13961371 hModule = LoadVersionModule (strInstallPath, dwLastError);
13971372 bFreeModule = hModule != NULL ;
@@ -1404,7 +1379,7 @@ void UpdateMTAVersionApplicationSetting(bool bQuiet)
14041379 if (!hModule)
14051380 {
14061381 const SString strBaseDirPath = GetMTASAPath ();
1407- if (IsUsableMtasaInstallRoot (strBaseDirPath) && !strBaseDirPath.CompareI (strInstallPath))
1382+ if (SharedUtil:: IsUsableMtasaInstallRoot (strBaseDirPath) && !strBaseDirPath.CompareI (strInstallPath))
14081383 {
14091384 hModule = LoadVersionModule (strBaseDirPath, dwLastError);
14101385 bFreeModule = hModule != NULL ;
0 commit comments