[0.4.7][RAPPS] Introduce 'SizeBytes' DB entry and use it for display

This will allow us to reduce the DB size a little by avoiding
duplication for each and every entry.
Original patch by JIRA user "swyter"

CORE-10310

fix picked from 0.4.9-dev-633-g 627739aed9
but slightly adopted to leave out some formatting glitches and
also leave out the "fall back to Size string" in available.cpp because
on 2021-10-03 Mark Jansen deleted all old size entries from the rapps database via
551e8cb95716f46e05c3be08996467bd93b1936f
This commit is contained in:
Joachim Henze 2022-01-14 22:50:13 +01:00
parent 7f018efb51
commit 1480d801ee
8 changed files with 378 additions and 99 deletions

View file

@ -9,6 +9,7 @@ include_directories(include)
list(APPEND SOURCE
aboutdlg.cpp
available.cpp
cabinet.cpp
gui.cpp
installed.cpp
integrity.cpp
@ -22,7 +23,6 @@ list(APPEND SOURCE
include/gui.h
include/dialogs.h
include/installed.h
include/cabinet.h
include/crichedit.h
include/defines.h
include/misc.h

View file

@ -38,7 +38,7 @@ VOID CAvailableApplicationInfo::RetrieveGeneralInfo()
{
m_Parser = new CConfigParser(m_sFileName);
m_Category = m_Parser->GetInt(L"Category");
m_Parser->GetInt(L"Category", m_Category);
if (!GetString(L"Name", m_szName)
|| !GetString(L"URLDownload", m_szUrlDownload))
@ -51,15 +51,16 @@ VOID CAvailableApplicationInfo::RetrieveGeneralInfo()
GetString(L"Version", m_szVersion);
GetString(L"License", m_szLicense);
GetString(L"Description", m_szDesc);
GetString(L"Size", m_szSize);
GetString(L"URLSite", m_szUrlSite);
GetString(L"CDPath", m_szCDPath);
GetString(L"Language", m_szRegName);
GetString(L"SHA1", m_szSHA1);
RetrieveSize();
RetrieveLicenseType();
RetrieveLanguages();
RetrieveInstalledStatus();
if (m_IsInstalled)
{
RetrieveInstalledVersion();
@ -128,7 +129,9 @@ VOID CAvailableApplicationInfo::RetrieveLanguages()
VOID CAvailableApplicationInfo::RetrieveLicenseType()
{
INT IntBuffer = m_Parser->GetInt(L"LicenseType");
INT IntBuffer;
m_Parser->GetInt(L"LicenseType", IntBuffer);
if (IsLicenseType(IntBuffer))
{
@ -140,6 +143,17 @@ VOID CAvailableApplicationInfo::RetrieveLicenseType()
}
}
VOID CAvailableApplicationInfo::RetrieveSize()
{
INT iSizeBytes;
if (!m_Parser->GetInt(L"SizeBytes", iSizeBytes))
return;
StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH);
m_szSize.ReleaseBuffer();
}
BOOL CAvailableApplicationInfo::FindInLanguages(LCID what) const
{
if (!m_HasLanguageInfo)
@ -213,7 +227,9 @@ AvailableStrings::AvailableStrings()
if (GetStorageDirectory(szPath))
{
szAppsPath = szPath + L"\\rapps\\";
szCabPath = szPath + L"\\rappmgr.cab";
szCabName = L"rappmgr.cab";
szCabDir = szPath;
szCabPath = (szCabDir + L"\\") + szCabName;
szSearchPath = szAppsPath + L"*.txt";
}
}
@ -282,7 +298,9 @@ BOOL CAvailableApps::UpdateAppsDB()
CDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL);
if (!ExtractFilesFromCab(m_Strings.szCabPath, m_Strings.szAppsPath))
if (!ExtractFilesFromCab(m_Strings.szCabName,
m_Strings.szCabDir,
m_Strings.szAppsPath))
{
return FALSE;
}

View file

@ -0,0 +1,334 @@
/*
* PROJECT: ReactOS Applications Manager
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* FILE: base/applications/rapps/cabinet.cpp
* PURPOSE: Cabinet extraction using FDI API
* COPYRIGHT: Copyright 2018 Alexander Shaposhnikov (sanchaez@reactos.org)
*/
#include "rapps.h"
#include <fdi.h>
#include <fcntl.h>
/*
* HACK: treat any input strings as Unicode (UTF-8)
* cabinet.dll lacks any sort of a Unicode API, but FCI/FDI
* provide an ability to use user-defined callbacks for any file or memory
* operations. This flexibility and the magic power of C/C++ casting allows
* us to treat input as we please.
* This is by far the best way to extract .cab using Unicode paths.
*/
/* String conversion helper functions */
// converts CStringW to CStringA using a given codepage
inline BOOL WideToMultiByte(const CStringW& szSource,
CStringA& szDest,
UINT Codepage)
{
// determine the needed size
INT sz = WideCharToMultiByte(Codepage,
0,
szSource,
-1,
NULL,
NULL,
NULL,
NULL);
if (!sz)
return FALSE;
// do the actual conversion
sz = WideCharToMultiByte(Codepage,
0,
szSource,
-1,
szDest.GetBuffer(sz),
sz,
NULL,
NULL);
szDest.ReleaseBuffer();
return sz != 0;
}
// converts CStringA to CStringW using a given codepage
inline BOOL MultiByteToWide(const CStringA& szSource,
CStringW& szDest,
UINT Codepage)
{
// determine the needed size
INT sz = MultiByteToWideChar(Codepage,
0,
szSource,
-1,
NULL,
NULL);
if (!sz)
return FALSE;
// do the actual conversion
sz = MultiByteToWideChar(CP_UTF8,
0,
szSource,
-1,
szDest.GetBuffer(sz),
sz);
szDest.ReleaseBuffer();
return sz != 0;
}
/* FDICreate callbacks */
FNALLOC(fnMemAlloc)
{
return HeapAlloc(GetProcessHeap(), NULL, cb);
}
FNFREE(fnMemFree)
{
HeapFree(GetProcessHeap(), NULL, pv);
}
FNOPEN(fnFileOpen)
{
HANDLE hFile = NULL;
DWORD dwDesiredAccess = 0;
DWORD dwCreationDisposition = 0;
ATL::CStringW szFileName;
UNREFERENCED_PARAMETER(pmode);
if (oflag & _O_RDWR)
{
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
}
else if (oflag & _O_WRONLY)
{
dwDesiredAccess = GENERIC_WRITE;
}
else
{
dwDesiredAccess = GENERIC_READ;
}
if (oflag & _O_CREAT)
{
dwCreationDisposition = CREATE_ALWAYS;
}
else
{
dwCreationDisposition = OPEN_EXISTING;
}
MultiByteToWide(pszFile, szFileName, CP_UTF8);
hFile = CreateFileW(szFileName,
dwDesiredAccess,
FILE_SHARE_READ,
NULL,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
NULL);
return (INT_PTR) hFile;
}
FNREAD(fnFileRead)
{
DWORD dwBytesRead = 0;
if (ReadFile((HANDLE) hf, pv, cb, &dwBytesRead, NULL) == FALSE)
{
dwBytesRead = (DWORD) -1L;
}
return dwBytesRead;
}
FNWRITE(fnFileWrite)
{
DWORD dwBytesWritten = 0;
if (WriteFile((HANDLE) hf, pv, cb, &dwBytesWritten, NULL) == FALSE)
{
dwBytesWritten = (DWORD) -1;
}
return dwBytesWritten;
}
FNCLOSE(fnFileClose)
{
return (CloseHandle((HANDLE) hf) != FALSE) ? 0 : -1;
}
FNSEEK(fnFileSeek)
{
return SetFilePointer((HANDLE) hf, dist, NULL, seektype);
}
/* FDICopy callbacks */
FNFDINOTIFY(fnNotify)
{
INT_PTR iResult = 0;
switch (fdint)
{
case fdintCOPY_FILE:
{
ATL::CStringW szNewFileName, szExtractDir, szCabFileName;
ATL::CStringA szFilePathUTF8;
// Append the destination directory to the file name.
MultiByteToWide((LPCSTR) pfdin->pv, szExtractDir, CP_UTF8);
MultiByteToWide(pfdin->psz1, szCabFileName, CP_ACP);
szNewFileName = szExtractDir + L"\\" + szCabFileName;
WideToMultiByte(szNewFileName, szFilePathUTF8, CP_UTF8);
// Copy file
iResult = fnFileOpen((LPSTR) szFilePathUTF8.GetString(),
_O_WRONLY | _O_CREAT,
0);
}
break;
case fdintCLOSE_FILE_INFO:
iResult = !fnFileClose(pfdin->hf);
break;
case fdintNEXT_CABINET:
if (pfdin->fdie != FDIERROR_NONE)
{
iResult = -1;
}
break;
case fdintPARTIAL_FILE:
iResult = 0;
break;
case fdintCABINET_INFO:
iResult = 0;
break;
case fdintENUMERATE:
iResult = 0;
break;
default:
iResult = -1;
break;
}
return iResult;
}
/* cabinet.dll FDI function pointers */
typedef HFDI(*fnFDICreate)(PFNALLOC,
PFNFREE,
PFNOPEN,
PFNREAD,
PFNWRITE,
PFNCLOSE,
PFNSEEK,
int,
PERF);
typedef BOOL(*fnFDICopy)(HFDI,
LPSTR,
LPSTR,
INT,
PFNFDINOTIFY,
PFNFDIDECRYPT,
void FAR *pvUser);
typedef BOOL(*fnFDIDestroy)(HFDI);
/*
* Extraction function
* TODO: require only a full path to the cab as an argument
*/
BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName,
const ATL::CStringW& szCabDir,
const ATL::CStringW& szOutputDir)
{
HINSTANCE hCabinetDll;
HFDI ExtractHandler;
ERF ExtractErrors;
ATL::CStringA szCabNameUTF8, szCabDirUTF8, szOutputDirUTF8;
fnFDICreate pfnFDICreate;
fnFDICopy pfnFDICopy;
fnFDIDestroy pfnFDIDestroy;
BOOL bResult;
// Load cabinet.dll and extract needed functions
hCabinetDll = LoadLibraryW(L"cabinet.dll");
if (!hCabinetDll)
{
return FALSE;
}
pfnFDICreate = (fnFDICreate) GetProcAddress(hCabinetDll, "FDICreate");
pfnFDICopy = (fnFDICopy) GetProcAddress(hCabinetDll, "FDICopy");
pfnFDIDestroy = (fnFDIDestroy) GetProcAddress(hCabinetDll, "FDIDestroy");
if (!pfnFDICreate || !pfnFDICopy || !pfnFDIDestroy)
{
FreeLibrary(hCabinetDll);
return FALSE;
}
// Create FDI context
ExtractHandler = pfnFDICreate(fnMemAlloc,
fnMemFree,
fnFileOpen,
fnFileRead,
fnFileWrite,
fnFileClose,
fnFileSeek,
cpuUNKNOWN,
&ExtractErrors);
if (!ExtractHandler)
{
FreeLibrary(hCabinetDll);
return FALSE;
}
// Create output dir
bResult = CreateDirectoryW(szOutputDir, NULL);
if (bResult || GetLastError() == ERROR_ALREADY_EXISTS)
{
// Convert wide strings to UTF-8
bResult = WideToMultiByte(szCabName, szCabNameUTF8, CP_UTF8);
bResult &= WideToMultiByte(szCabDir, szCabDirUTF8, CP_UTF8);
bResult &= WideToMultiByte(szOutputDir, szOutputDirUTF8, CP_UTF8);
}
// Perform extraction
if (bResult)
{
// Add a slash to cab name as required by the api
szCabNameUTF8 = "\\" + szCabNameUTF8;
bResult = pfnFDICopy(ExtractHandler,
(LPSTR) szCabNameUTF8.GetString(),
(LPSTR) szCabDirUTF8.GetString(),
0,
fnNotify,
NULL,
(void FAR *) szOutputDirUTF8.GetString());
}
pfnFDIDestroy(ExtractHandler);
FreeLibrary(hCabinetDll);
return bResult;
}

View file

@ -75,6 +75,7 @@ private:
VOID RetrieveInstalledVersion();
VOID RetrieveLanguages();
VOID RetrieveLicenseType();
VOID RetrieveSize();
inline BOOL FindInLanguages(LCID what) const;
};
@ -86,6 +87,8 @@ struct AvailableStrings
ATL::CStringW szCabPath;
ATL::CStringW szAppsPath;
ATL::CStringW szSearchPath;
ATL::CStringW szCabName;
ATL::CStringW szCabDir;
AvailableStrings();
};

View file

@ -1,32 +0,0 @@
// Structs related to .cab extraction
// FIXME: they should belong to exports of cabinet.dll
#pragma once
struct ERF
{
INT erfOper;
INT erfType;
BOOL fError;
};
struct FILELIST
{
LPSTR FileName;
FILELIST *next;
BOOL DoExtract;
};
struct SESSION
{
INT FileSize;
ERF Error;
FILELIST *FileList;
INT FileCount;
INT Operation;
CHAR Destination[MAX_PATH];
CHAR CurrentFile[MAX_PATH];
CHAR Reserved[MAX_PATH];
FILELIST *FilterList;
};
typedef HRESULT(WINAPI *fnExtract)(SESSION *dest, LPCSTR szCabName);

View file

@ -14,12 +14,16 @@ VOID ShowPopupMenu(HWND hwnd, UINT MenuID, UINT DefaultItem);
BOOL StartProcess(ATL::CStringW &Path, BOOL Wait);
BOOL StartProcess(LPWSTR lpPath, BOOL Wait);
BOOL GetStorageDirectory(ATL::CStringW &lpDirectory);
BOOL ExtractFilesFromCab(LPCWSTR lpCabName, LPCWSTR lpOutputPath);
VOID InitLogs();
VOID FreeLogs();
BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg);
BOOL GetInstalledVersion(ATL::CStringW *pszVersion, const ATL::CStringW &szRegName);
BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName,
const ATL::CStringW& szCabDir,
const ATL::CStringW& szOutputDir);
class CConfigParser
{
// Locale names cache
@ -37,6 +41,6 @@ class CConfigParser
public:
CConfigParser(const ATL::CStringW& FileName = "");
UINT GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString);
UINT GetInt(const ATL::CStringW& KeyName);
BOOL GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString);
BOOL GetInt(const ATL::CStringW& KeyName, INT& iResult);
};

View file

@ -154,6 +154,9 @@
#define IDS_AINFO_URLDOWNLOAD 355
#define IDS_AINFO_AVAILABLEVERSION 356
#define IDS_AINFO_LANGUAGES 357
#define IDS_AINFO_KILOBYTE_EXT 358
#define IDS_AINFO_MEGABYTE_EXT 359
#define IDS_AINFO_GIGABYTE_EXT 360
/* Names of categories */

View file

@ -11,11 +11,6 @@
#include "gui.h"
#include "misc.h"
#include "cabinet.h"
/* SESSION Operation */
#define EXTRACT_FILLFILELIST 0x00000001
#define EXTRACT_EXTRACTFILES 0x00000002
static HANDLE hLog = NULL;
@ -203,55 +198,6 @@ BOOL GetStorageDirectory(ATL::CStringW& Directory)
return (CreateDirectoryW(Directory.GetString(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS);
}
BOOL ExtractFilesFromCab(const ATL::CStringW &CabName, const ATL::CStringW &OutputPath)
{
return ExtractFilesFromCab(CabName.GetString(), OutputPath.GetString());
}
BOOL ExtractFilesFromCab(LPCWSTR lpCabName, LPCWSTR lpOutputPath)
{
HINSTANCE hCabinetDll;
CHAR szCabName[MAX_PATH];
SESSION Dest;
HRESULT Result;
fnExtract pfnExtract;
hCabinetDll = LoadLibraryW(L"cabinet.dll");
if (hCabinetDll)
{
pfnExtract = (fnExtract) GetProcAddress(hCabinetDll, "Extract");
if (pfnExtract)
{
ZeroMemory(&Dest, sizeof(Dest));
WideCharToMultiByte(CP_ACP, 0, lpOutputPath, -1, Dest.Destination, MAX_PATH, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, lpCabName, -1, szCabName, _countof(szCabName), NULL, NULL);
Dest.Operation = EXTRACT_FILLFILELIST;
Result = pfnExtract(&Dest, szCabName);
if (Result == S_OK)
{
Dest.Operation = EXTRACT_EXTRACTFILES;
CreateDirectoryW(lpOutputPath, NULL);
Result = pfnExtract(&Dest, szCabName);
if (Result == S_OK)
{
FreeLibrary(hCabinetDll);
return TRUE;
}
else
{
RemoveDirectoryW(lpOutputPath);
}
}
}
FreeLibrary(hCabinetDll);
}
return FALSE;
}
VOID InitLogs()
{
if (!SettingsInfo.bLogEnabled)
@ -408,7 +354,7 @@ VOID CConfigParser::CacheINILocale()
m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale + m_szLocaleID.Right(2);
}
UINT CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
{
DWORD dwResult;
@ -446,10 +392,12 @@ UINT CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& Resul
return (dwResult != 0 ? TRUE : FALSE);
}
UINT CConfigParser::GetInt(const ATL::CStringW& KeyName)
BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult)
{
ATL::CStringW Buffer;
iResult = 0;
// grab the text version of our entry
if (!GetString(KeyName, Buffer))
return FALSE;
@ -458,8 +406,9 @@ UINT CConfigParser::GetInt(const ATL::CStringW& KeyName)
return FALSE;
// convert it to an actual integer
INT result = StrToIntW(Buffer.GetString());
iResult = StrToIntW(Buffer.GetString());
return (UINT) (result <= 0) ? 0 : result;
// we only care about values > 0
return (iResult > 0);
}
// CConfigParser