3rdparty: Update rainterface to commit 5d763c2

This commit is contained in:
JordanTheToaster
2026-03-11 16:51:14 +01:00
committed by lightningterror
parent 8de55a1937
commit 247511fd38
2 changed files with 227 additions and 62 deletions
+14 -1
View File
@@ -1,7 +1,7 @@
#ifndef RA_CONSOLES_H
#define RA_CONSOLES_H
/* this list should match the list in rcheevos/include/rconsoles.h */
/* this list should match the list in rcheevos/include/rc_consoles.h */
enum ConsoleID
{
UnknownConsoleID = 0,
@@ -77,6 +77,19 @@ enum ConsoleID
Zeebo = 70,
Arduboy = 71,
WASM4 = 72,
Arcadia2001 = 73,
IntertonVC4000 = 74,
ElektorTVGamesComputer = 75,
PCEngineCD = 76,
JaguarCD = 77,
DSi = 78,
TI83 = 79,
Uzebox = 80,
FamicomDiskSystem = 81,
Hubs = 100,
Events = 101,
Standalone = 102,
NumConsoleIDs
};
+213 -61
View File
@@ -5,10 +5,23 @@
#include <stdexcept>
#include <string>
#ifndef RA_NOPROGRESS
#include <ShlObj.h>
#else
#define IProgressDialog void
#endif
#ifndef CCONV
#define CCONV __cdecl
#endif
#if defined(_M_X64) || defined(__amd64__)
#define RA_X64
#define RA_INT_DLL L"RA_Integration-x64.dll"
#else
#define RA_INT_DLL L"RA_Integration.dll"
#endif
// Initialization
static const char* (CCONV* _RA_IntegrationVersion)() = nullptr;
static const char* (CCONV* _RA_HostName)() = nullptr;
@@ -270,10 +283,58 @@ void RA_DisableHardcore()
_RA_WarnDisableHardcore(nullptr);
}
static size_t DownloadToFile(char* pData, size_t nDataSize, void* pUserData)
#ifndef RA_NOPROGRESS
static void FormatByteSize(DWORD nSize, wchar_t* sBuffer, size_t nBufferSize)
{
if (nSize < 1024)
{
swprintf_s(sBuffer, nBufferSize, L"%u bytes", nSize);
return;
}
float fSize = nSize;
fSize /= 1024.0;
if (fSize < 1024.0)
{
swprintf_s(sBuffer, nBufferSize, L"%.2f KB", fSize);
return;
}
fSize /= 1024.0;
swprintf_s(sBuffer, nBufferSize, L"%.2f MB", fSize);
}
static void SetProgressMessage(IProgressDialog* pProgressDialog, DWORD nProgress, DWORD nMax)
{
wchar_t sNum[32];
std::wstring sMessage;
FormatByteSize(nProgress, sNum, sizeof(sNum) / sizeof(sNum[0]));
sMessage.append(sNum);
sMessage.append(L" of ");
FormatByteSize(nMax, sNum, sizeof(sNum) / sizeof(sNum[0]));
sMessage.append(sNum);
pProgressDialog->SetLine(2, sMessage.c_str(), FALSE, NULL);
}
#endif
static size_t DownloadToFile(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode)
{
FILE* file = (FILE*)pUserData;
return fwrite(pData, 1, nDataSize, file);
size_t nBytesWritten = fwrite(pData, 1, nDataSize, file);
if (nBytesWritten != nDataSize)
{
std::string sMessage;
sMessage = "Error " + std::to_string(errno) + " writing file: " + strerror(errno);
MessageBoxA(nullptr, sMessage.c_str(), "Error", MB_OK | MB_ICONERROR);
*pStatusCode = 0;
}
return nBytesWritten;
}
typedef struct DownloadBuffer
@@ -283,7 +344,7 @@ typedef struct DownloadBuffer
size_t nOffset;
} DownloadBuffer;
static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData)
static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode)
{
DownloadBuffer* pBuffer = (DownloadBuffer*)pUserData;
const size_t nRemaining = pBuffer->nBufferSize - pBuffer->nOffset;
@@ -299,10 +360,10 @@ static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData)
return nDataSize;
}
typedef size_t (DownloadFunc)(char* pData, size_t nDataSize, void* pUserData);
typedef size_t (DownloadFunc)(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode);
static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage, const char* sPostData,
DownloadFunc fnDownload, void* pDownloadUserData, DWORD* pBytesRead, DWORD* pStatusCode)
DownloadFunc fnDownload, void* pDownloadUserData, DWORD* pBytesRead, DWORD* pStatusCode, IProgressDialog* pProgressDialog)
{
BOOL bResults = FALSE, bSuccess = FALSE;
HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr;
@@ -355,6 +416,8 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
mbstowcs_s(&nTemp, wBuffer, sizeof(wBuffer) / sizeof(wBuffer[0]), sHostName, nHostnameLen);
#else
nTemp = mbstowcs(wBuffer, sHostName, nHostnameLen);
if (nTemp > 0)
wBuffer[nTemp] = '\0';
#endif
if (nTemp > 0)
@@ -373,6 +436,8 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
mbstowcs_s(&nTemp, wBuffer, sizeof(wBuffer) / sizeof(wBuffer[0]), sRequestedPage, strlen(sRequestedPage) + 1);
#else
nTemp = mbstowcs(wBuffer, sRequestedPage, strlen(sRequestedPage) + 1);
if (nTemp > 0)
wBuffer[nTemp] = '\0';
#endif
hRequest = WinHttpOpenRequest(hConnect,
@@ -410,12 +475,28 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
}
else
{
char buffer[16384];
const DWORD nBufferSize = 16384;
char* pBuffer = (char*)malloc(nBufferSize);
DWORD dwSize = sizeof(DWORD);
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, pStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX);
bSuccess = (*pStatusCode == 200);
const DWORD nDefaultTotalBytes = 3 * 1024 * 1024;
DWORD nTotalBytes = nDefaultTotalBytes;
bSuccess = TRUE;
do
#ifndef RA_NOPROGRESS
if (pProgressDialog)
{
dwSize = nBufferSize;
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, pBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX))
{
nTotalBytes = wcstoul((const wchar_t*)pBuffer, NULL, 10);
SetProgressMessage(pProgressDialog, 0, nTotalBytes);
}
}
#endif
while (bSuccess)
{
nBytesAvailable = 0;
WinHttpQueryDataAvailable(hRequest, &nBytesAvailable);
@@ -424,20 +505,17 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
do
{
if (nBytesAvailable > sizeof(buffer))
nBytesToRead = sizeof(buffer);
if (nBytesAvailable > nBufferSize)
nBytesToRead = nBufferSize;
else
nBytesToRead = nBytesAvailable;
nBytesFetched = 0;
if (WinHttpReadData(hRequest, buffer, nBytesToRead, &nBytesFetched))
if (WinHttpReadData(hRequest, pBuffer, nBytesToRead, &nBytesFetched))
{
size_t nBytesWritten = fnDownload(buffer, nBytesFetched, pDownloadUserData);
size_t nBytesWritten = fnDownload(pBuffer, nBytesFetched, pDownloadUserData, pStatusCode);
if (nBytesWritten < nBytesFetched)
{
if (*pStatusCode == 200)
*pStatusCode = 998;
bSuccess = FALSE;
break;
}
@@ -453,8 +531,27 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
bSuccess = FALSE;
break;
}
#ifndef RA_NOPROGRESS
if (pProgressDialog)
{
if (pProgressDialog->HasUserCancelled())
{
bSuccess = FALSE;
*pStatusCode = 0;
break;
}
pProgressDialog->SetProgress(*pBytesRead, nTotalBytes);
if (nTotalBytes != nDefaultTotalBytes)
SetProgressMessage(pProgressDialog, *pBytesRead, nTotalBytes);
}
#endif
} while (nBytesAvailable > 0);
} while (TRUE);
};
free(pBuffer);
}
WinHttpCloseHandle(hRequest);
@@ -502,7 +599,7 @@ static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sReque
downloadBuffer.pBuffer = pBufferOut;
downloadBuffer.nBufferSize = nBufferOutSize;
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToBuffer, &downloadBuffer, pBytesRead, pStatusCode) != FALSE)
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToBuffer, &downloadBuffer, pBytesRead, pStatusCode, NULL) != FALSE)
return TRUE;
if (!IsNetworkError(*pStatusCode))
@@ -515,26 +612,54 @@ static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sReque
}
static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sRequestedPage, const char* sPostData,
FILE* pFile, DWORD* pBytesRead, DWORD* pStatusCode)
FILE* pFile, DWORD* pBytesRead, DWORD* pStatusCode, const wchar_t* sMessage)
{
int nRetries = 4;
do
{
fseek(pFile, 0, SEEK_SET);
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToFile, pFile, pBytesRead, pStatusCode) != FALSE)
return TRUE;
IProgressDialog* pProgressDialog = NULL;
#ifndef RA_NOPROGRESS
HRESULT hrInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
HRESULT hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (LPVOID*)&pProgressDialog);
if (!IsNetworkError(*pStatusCode))
return FALSE;
if (SUCCEEDED(hr))
{
if (sMessage)
pProgressDialog->SetLine(1, sMessage, FALSE, NULL);
pProgressDialog->StartProgressDialog(NULL, NULL, PROGDLG_NORMAL, NULL);
}
#endif
--nRetries;
} while (nRetries);
BOOL success = FALSE;
int nRetries = 4;
do
{
fseek(pFile, 0, SEEK_SET);
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToFile, pFile, pBytesRead, pStatusCode, pProgressDialog) != FALSE)
{
success = TRUE;
break;
}
return FALSE;
if (!IsNetworkError(*pStatusCode))
break;
--nRetries;
} while (nRetries);
#ifndef RA_NOPROGRESS
if (pProgressDialog)
{
pProgressDialog->StopProgressDialog();
pProgressDialog->Release();
}
if (hrInit == S_OK)
CoUninitialize();
#endif
return success;
}
#ifndef RA_UTEST
static std::wstring GetIntegrationPath()
static std::wstring GetIntegrationPath(const wchar_t* sFilename)
{
wchar_t sBuffer[2048];
DWORD iIndex = GetModuleFileNameW(0, sBuffer, 2048);
@@ -542,29 +667,33 @@ static std::wstring GetIntegrationPath()
--iIndex;
#if defined(_MSC_VER) && _MSC_VER >= 1400
wcscpy_s(&sBuffer[iIndex], sizeof(sBuffer)/sizeof(sBuffer[0]) - iIndex, L"RA_Integration.dll");
wcscpy_s(&sBuffer[iIndex], sizeof(sBuffer)/sizeof(sBuffer[0]) - iIndex, sFilename);
#else
wcscpy(&sBuffer[iIndex], L"RA_Integration.dll");
wcscpy(&sBuffer[iIndex], sFilename);
#endif
return std::wstring(sBuffer);
}
#endif
#if 0
static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
{
DWORD nBytesRead = 0;
const wchar_t* sDownloadFilename = L"RA_Integration.download";
const wchar_t* sFilename = L"RA_Integration.dll";
const wchar_t* sOldFilename = L"RA_Integration.old";
const std::wstring sDownloadFilename = GetIntegrationPath(RA_INT_DLL ".download");
const std::wstring sOldFilename = GetIntegrationPath(RA_INT_DLL ".old");
const std::wstring sNewFilename = GetIntegrationPath(RA_INT_DLL);
std::wstring sFilename = sNewFilename;
#ifdef RA_X64
if (GetFileAttributesW(sFilename.c_str()) == INVALID_FILE_ATTRIBUTES)
sFilename = GetIntegrationPath(L"RA_Integration.dll");
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400
FILE* pf;
errno_t nErr = _wfopen_s(&pf, sDownloadFilename, L"wb");
errno_t nErr = _wfopen_s(&pf, sDownloadFilename.c_str(), L"wb");
#else
FILE* pf = _wfopen(sDownloadFilename, L"wb");
FILE* pf = _wfopen(sDownloadFilename.c_str(), L"wb");
#endif
if (!pf)
@@ -573,12 +702,13 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
wchar_t sErrBuffer[2048];
_wcserror_s(sErrBuffer, sizeof(sErrBuffer) / sizeof(sErrBuffer[0]), nErr);
std::wstring sErrMsg = std::wstring(L"Unable to write ") + sOldFilename + L"\n" + sErrBuffer;
std::wstring sErrMsg = std::wstring(L"Unable to write " RA_INT_DLL L".download\n") + sErrBuffer;
#else
std::wstring sErrMsg = std::wstring(L"Unable to write ") + sOldFilename + L"\n" + _wcserror(errno);
std::wstring sErrMsg = std::wstring(L"Unable to write " RA_INT_DLL L".download\n") + _wcserror(errno);
#endif
MessageBoxW(nullptr, sErrMsg.c_str(), L"Error", MB_OK | MB_ICONERROR);
*pStatusCode = 0;
return;
}
@@ -594,36 +724,36 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
}
*pSplit++ = '\0';
if (DoBlockingHttpCallWithRetry(sLatestVersionUrl, pSplit, nullptr, pf, &nBytesRead, pStatusCode))
if (DoBlockingHttpCallWithRetry(sLatestVersionUrl, pSplit, nullptr, pf, &nBytesRead, pStatusCode, "Downloading " RA_INT_DLL))
{
fclose(pf);
/* wait up to one second for the DLL to actually be released - sometimes it's not immediate */
for (int i = 0; i < 10; i++)
{
if (GetModuleHandleW(sFilename) == nullptr)
if (GetModuleHandleW(sFilename.c_str()) == nullptr)
break;
Sleep(100);
}
// delete the last old dll if it's still present
DeleteFileW(sOldFilename);
DeleteFileW(sOldFilename.c_str());
// if there's a dll present, rename it
if (GetFileAttributesW(sFilename) != INVALID_FILE_ATTRIBUTES &&
!MoveFileW(sFilename, sOldFilename))
if (GetFileAttributesW(sFilename.c_str()) != INVALID_FILE_ATTRIBUTES &&
!MoveFileW(sFilename.c_str(), sOldFilename.c_str()))
{
MessageBoxW(nullptr, L"Could not rename old dll", L"Error", MB_OK | MB_ICONERROR);
}
// rename the download to be the dll
else if (!MoveFileW(sDownloadFilename, sFilename))
else if (!MoveFileW(sDownloadFilename.c_str(), sNewFilename.c_str()))
{
MessageBoxW(nullptr, L"Could not rename new dll", L"Error", MB_OK | MB_ICONERROR);
}
// delete the old dll
DeleteFileW(sOldFilename);
DeleteFileW(sOldFilename.c_str());
}
else
{
@@ -631,8 +761,6 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
}
}
#endif
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
static std::string GetLastErrorAsString()
{
@@ -657,9 +785,15 @@ static const char* CCONV _RA_InstallIntegration()
{
SetErrorMode(0);
std::wstring sIntegrationPath = GetIntegrationPath();
std::wstring sIntegrationPath = GetIntegrationPath(RA_INT_DLL);
DWORD dwAttrib = GetFileAttributesW(sIntegrationPath.c_str());
#ifdef RA_X64
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
sIntegrationPath = GetIntegrationPath(L"RA_Integration.dll");
dwAttrib = GetFileAttributesW(sIntegrationPath.c_str());
}
#endif
if (dwAttrib == INVALID_FILE_ATTRIBUTES)
return "0.0";
@@ -667,7 +801,23 @@ static const char* CCONV _RA_InstallIntegration()
if (g_hRADLL == nullptr)
{
char buffer[1024];
sprintf_s(buffer, 1024, "Could not load RA_Integration.dll: %d\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
if (::GetLastError() == ERROR_BAD_EXE_FORMAT)
{
#ifdef RA_X64
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration-x64.dll (error %d)\nAre you trying to load the 32-bit version?\n", ::GetLastError());
#else
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration.dll (error %d)\nAre you trying to load the 64-bit version?\n", ::GetLastError());
#endif
}
else
{
#ifdef RA_X64
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration-x64.dll (error %d)\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
#else
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration.dll (error %d)\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
#endif
}
MessageBoxA(nullptr, buffer, "Warning", MB_OK | MB_ICONWARNING);
return "0.0";
@@ -876,7 +1026,7 @@ static void RA_InitCommon(HWND hMainHWND, int nEmulatorID, const char* sClientNa
GetJsonField(buffer, "LatestVersion", sVersionBuffer, sizeof(sVersionBuffer));
const unsigned long long nLatestDLLVer = ParseVersion(sVersionBuffer);
#if defined(_M_X64) || defined(__amd64__)
#ifdef RA_X64
GetJsonField(buffer, "LatestVersionUrlX64", sLatestVersionUrl, sizeof(sLatestVersionUrl));
#else
GetJsonField(buffer, "LatestVersionUrl", sLatestVersionUrl, sizeof(sLatestVersionUrl));
@@ -930,16 +1080,18 @@ static void RA_InitCommon(HWND hMainHWND, int nEmulatorID, const char* sClientNa
if (nMBReply == IDYES)
{
//FetchIntegrationFromWeb(sLatestVersionUrl, &nStatusCode);
nStatusCode = 0;
FetchIntegrationFromWeb(sLatestVersionUrl, &nStatusCode);
if (nStatusCode == 200)
nVerInstalled = ParseVersion(_RA_InstallIntegration());
if (nVerInstalled < nLatestDLLVer)
if (nStatusCode != 0) // 0 indicates an error was already reported
{
sprintf_s(buffer, sizeof(buffer), "Failed to update toolset (status code %u).", nStatusCode);
MessageBoxA(hMainHWND, buffer, "Error", MB_OK | MB_ICONERROR);
if (nStatusCode == 200)
nVerInstalled = ParseVersion(_RA_InstallIntegration());
if (nVerInstalled < nLatestDLLVer)
{
sprintf_s(buffer, sizeof(buffer), "Failed to update toolset (status code %u).", nStatusCode);
MessageBoxA(hMainHWND, buffer, "Error", MB_OK | MB_ICONERROR);
}
}
}