mirror of
https://github.com/reactos/reactos.git
synced 2025-07-12 19:14:18 +00:00
[RAPPS] Add ExeInZip installer type to support running installers in zip files (#7866)
This commit is contained in:
parent
eb91f91569
commit
37e2c59096
8 changed files with 111 additions and 25 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include "appdb.h"
|
#include "appdb.h"
|
||||||
#include "configparser.h"
|
#include "configparser.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
|
||||||
static HKEY g_RootKeyEnum[3] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE};
|
static HKEY g_RootKeyEnum[3] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE};
|
||||||
|
@ -34,6 +35,14 @@ CAppDB::CAppDB(const CStringW &path) : m_BasePath(path)
|
||||||
m_BasePath.Canonicalize();
|
m_BasePath.Canonicalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CStringW
|
||||||
|
CAppDB::GetDefaultPath()
|
||||||
|
{
|
||||||
|
CStringW path;
|
||||||
|
GetStorageDirectory(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
CAvailableApplicationInfo *
|
CAvailableApplicationInfo *
|
||||||
CAppDB::FindAvailableByPackageName(const CStringW &name)
|
CAppDB::FindAvailableByPackageName(const CStringW &name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -380,10 +380,11 @@ CAvailableApplicationInfo::GetInstallerType() const
|
||||||
{
|
{
|
||||||
CStringW str;
|
CStringW str;
|
||||||
m_Parser->GetString(DB_INSTALLER, str);
|
m_Parser->GetString(DB_INSTALLER, str);
|
||||||
if (str.CompareNoCase(DB_GENINSTSECTION) == 0)
|
if (str.CompareNoCase(DB_INSTALLER_GENERATE) == 0)
|
||||||
return INSTALLER_GENERATE;
|
return INSTALLER_GENERATE;
|
||||||
else
|
if (str.CompareNoCase(DB_INSTALLER_EXEINZIP) == 0)
|
||||||
return INSTALLER_UNKNOWN;
|
return INSTALLER_EXEINZIP;
|
||||||
|
return INSTALLER_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
|
|
@ -60,7 +60,7 @@ BOOL IsZipFile(PCWSTR Path)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ExtractFilesFromZip(LPCWSTR Archive, const CStringW &OutputDir,
|
ExtractFilesFromZip(LPCWSTR Archive, const CStringW &OutputDir,
|
||||||
EXTRACTCALLBACK Callback, void *Cookie)
|
EXTRACTCALLBACK Callback, void *Context)
|
||||||
{
|
{
|
||||||
const UINT pkzefsutf8 = 1 << 11; // APPNOTE; APPENDIX D
|
const UINT pkzefsutf8 = 1 << 11; // APPNOTE; APPENDIX D
|
||||||
zlib_filefunc64_def zff;
|
zlib_filefunc64_def zff;
|
||||||
|
@ -97,7 +97,7 @@ ExtractFilesFromZip(LPCWSTR Archive, const CStringW &OutputDir,
|
||||||
fileatt = LOBYTE(fi.external_fa);
|
fileatt = LOBYTE(fi.external_fa);
|
||||||
|
|
||||||
if (!NotifyFileExtractCallback(path, fi.uncompressed_size, fileatt,
|
if (!NotifyFileExtractCallback(path, fi.uncompressed_size, fileatt,
|
||||||
Callback, Cookie))
|
Callback, Context))
|
||||||
continue; // Skip file
|
continue; // Skip file
|
||||||
|
|
||||||
path = BuildPath(OutputDir, path);
|
path = BuildPath(OutputDir, path);
|
||||||
|
@ -136,22 +136,31 @@ ExtractFilesFromZip(LPCWSTR Archive, const CStringW &OutputDir,
|
||||||
|
|
||||||
static UINT
|
static UINT
|
||||||
ExtractZip(LPCWSTR Archive, const CStringW &OutputDir,
|
ExtractZip(LPCWSTR Archive, const CStringW &OutputDir,
|
||||||
EXTRACTCALLBACK Callback, void *Cookie)
|
EXTRACTCALLBACK Callback, void *Context)
|
||||||
{
|
{
|
||||||
int zerr = ExtractFilesFromZip(Archive, OutputDir, Callback, Cookie);
|
int zerr = ExtractFilesFromZip(Archive, OutputDir, Callback, Context);
|
||||||
return zerr == UNZ_ERRNO ? GetLastError() : zerr ? ERROR_INTERNAL_ERROR : 0;
|
return zerr == UNZ_ERRNO ? GetLastError() : zerr ? ERROR_INTERNAL_ERROR : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT
|
static UINT
|
||||||
ExtractCab(LPCWSTR Archive, const CStringW &OutputDir,
|
ExtractCab(LPCWSTR Archive, const CStringW &OutputDir,
|
||||||
EXTRACTCALLBACK Callback, void *Cookie)
|
EXTRACTCALLBACK Callback, void *Context)
|
||||||
{
|
{
|
||||||
if (ExtractFilesFromCab(Archive, OutputDir, Callback, Cookie))
|
if (ExtractFilesFromCab(Archive, OutputDir, Callback, Context))
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
UINT err = GetLastError();
|
UINT err = GetLastError();
|
||||||
return err ? err : ERROR_INTERNAL_ERROR;
|
return err ? err : ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static UINT
|
||||||
|
ExtractArchive(LPCWSTR Archive, const CStringW &OutputDir, EXTRACTCALLBACK Callback, void *Context)
|
||||||
|
{
|
||||||
|
BOOL isCab = LOBYTE(ClassifyFile(Archive)) == 'C';
|
||||||
|
return isCab ? ExtractCab(Archive, OutputDir, Callback, Context)
|
||||||
|
: ExtractZip(Archive, OutputDir, Callback, Context);
|
||||||
|
}
|
||||||
|
|
||||||
enum { IM_STARTPROGRESS = WM_APP, IM_PROGRESS, IM_END };
|
enum { IM_STARTPROGRESS = WM_APP, IM_PROGRESS, IM_END };
|
||||||
|
|
||||||
static struct CommonInfo
|
static struct CommonInfo
|
||||||
|
@ -430,9 +439,9 @@ AddUninstallOperationsFromDB(LPCWSTR Name, WCHAR UnOp, CStringW PathPrefix = CSt
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL CALLBACK
|
static BOOL CALLBACK
|
||||||
ExtractCallback(const EXTRACTCALLBACKINFO &, void *Cookie)
|
ExtractCallback(const EXTRACTCALLBACKINFO &, void *Context)
|
||||||
{
|
{
|
||||||
InstallInfo &Info = *(InstallInfo *) Cookie;
|
InstallInfo &Info = *(InstallInfo *)Context;
|
||||||
Info.Count += 1;
|
Info.Count += 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -501,11 +510,7 @@ ExtractAndInstallThread(LPVOID Parameter)
|
||||||
ErrorBox(Info.Error);
|
ErrorBox(Info.Error);
|
||||||
|
|
||||||
if (!Info.Error)
|
if (!Info.Error)
|
||||||
{
|
Info.Error = ExtractArchive(Archive, tempdir, ExtractCallback, &Info);
|
||||||
BOOL isCab = LOBYTE(ClassifyFile(tempdir)) == 'C';
|
|
||||||
Info.Error = isCab ? ExtractCab(Archive, tempdir, ExtractCallback, &Info)
|
|
||||||
: ExtractZip(Archive, tempdir, ExtractCallback, &Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Info.Error)
|
if (!Info.Error)
|
||||||
{
|
{
|
||||||
|
@ -835,3 +840,46 @@ UninstallGenerated(CInstalledApplicationInfo &AppInfo, UninstallCommandFlags Fla
|
||||||
g_pInfo = &Info;
|
g_pInfo = &Info;
|
||||||
return CreateUI(Info.Silent, UninstallThread) ? !Info.Error : FALSE;
|
return CreateUI(Info.Silent, UninstallThread) ? !Info.Error : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
ExtractArchiveForExecution(PCWSTR pszArchive, const CStringW &PackageName, CStringW &TempDir, CStringW &App)
|
||||||
|
{
|
||||||
|
WCHAR TempDirBuf[MAX_PATH], UniqueDir[MAX_PATH];
|
||||||
|
CAppDB db(CAppDB::GetDefaultPath());
|
||||||
|
db.UpdateAvailable();
|
||||||
|
CAvailableApplicationInfo *pAppInfo = db.FindAvailableByPackageName(PackageName);
|
||||||
|
if (!pAppInfo)
|
||||||
|
return HResultFromWin32(ERROR_NOT_FOUND);
|
||||||
|
CConfigParser *pCfg = pAppInfo->GetConfigParser();
|
||||||
|
|
||||||
|
if (!GetTempPathW(_countof(TempDirBuf), TempDirBuf))
|
||||||
|
return E_FAIL;
|
||||||
|
wsprintfW(UniqueDir, L"~%s-%u", RAPPS_NAME, GetCurrentProcessId());
|
||||||
|
TempDir = BuildPath(TempDirBuf, UniqueDir);
|
||||||
|
HRESULT hr = HResultFromWin32(CreateDirectoryTree(TempDir));
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = HResultFromWin32(ExtractArchive(pszArchive, TempDir, NULL, NULL));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CStringW Exe;
|
||||||
|
if (pCfg->GetSectionString(DB_EXEINZIPSECTION, DB_EXEINZIP_EXE, Exe) <= 0)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATAW wfd;
|
||||||
|
HANDLE hFind = FindFirstFileW(Exe = BuildPath(TempDir, L"*.exe"), &wfd);
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
FindClose(hFind);
|
||||||
|
Exe = wfd.cFileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
App = BuildPath(TempDir, Exe);
|
||||||
|
if (GetFileAttributesW(App) & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
hr = HResultFromWin32(ERROR_FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr) && !TempDir.IsEmpty())
|
||||||
|
DeleteDirectoryTree(TempDir, hMainWnd);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ class CAppDB
|
||||||
public:
|
public:
|
||||||
CAppDB(const CStringW &path);
|
CAppDB(const CStringW &path);
|
||||||
|
|
||||||
|
static CStringW
|
||||||
|
GetDefaultPath();
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
GetApps(CAtlList<CAppInfo *> &List, AppsCategories Type) const;
|
GetApps(CAtlList<CAppInfo *> &List, AppsCategories Type) const;
|
||||||
CAvailableApplicationInfo *
|
CAvailableApplicationInfo *
|
||||||
|
|
|
@ -83,6 +83,7 @@ enum InstallerType
|
||||||
{
|
{
|
||||||
INSTALLER_UNKNOWN,
|
INSTALLER_UNKNOWN,
|
||||||
INSTALLER_GENERATE, // .zip file automatically converted to installer by rapps
|
INSTALLER_GENERATE, // .zip file automatically converted to installer by rapps
|
||||||
|
INSTALLER_EXEINZIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DB_VERSION L"Version"
|
#define DB_VERSION L"Version"
|
||||||
|
@ -90,12 +91,17 @@ enum InstallerType
|
||||||
#define DB_PUBLISHER L"Publisher"
|
#define DB_PUBLISHER L"Publisher"
|
||||||
#define DB_REGNAME L"RegName"
|
#define DB_REGNAME L"RegName"
|
||||||
#define DB_INSTALLER L"Installer"
|
#define DB_INSTALLER L"Installer"
|
||||||
|
#define DB_INSTALLER_GENERATE L"Generate"
|
||||||
|
#define DB_INSTALLER_EXEINZIP L"ExeInZip"
|
||||||
#define DB_SCOPE L"Scope" // User or Machine
|
#define DB_SCOPE L"Scope" // User or Machine
|
||||||
#define DB_SAVEAS L"SaveAs"
|
#define DB_SAVEAS L"SaveAs"
|
||||||
|
|
||||||
#define DB_GENINSTSECTION L"Generate"
|
#define DB_GENINSTSECTION L"Generate"
|
||||||
#define GENERATE_ARPSUBKEY L"RApps" // Our uninstall data is stored here
|
#define GENERATE_ARPSUBKEY L"RApps" // Our uninstall data is stored here
|
||||||
|
|
||||||
|
#define DB_EXEINZIPSECTION L"ExeInZip"
|
||||||
|
#define DB_EXEINZIP_EXE L"Exe"
|
||||||
|
|
||||||
class CAppRichEdit;
|
class CAppRichEdit;
|
||||||
class CConfigParser;
|
class CConfigParser;
|
||||||
|
|
||||||
|
@ -234,3 +240,5 @@ BOOL
|
||||||
UninstallGenerated(CInstalledApplicationInfo &AppInfo, UninstallCommandFlags Flags);
|
UninstallGenerated(CInstalledApplicationInfo &AppInfo, UninstallCommandFlags Flags);
|
||||||
BOOL
|
BOOL
|
||||||
ExtractAndRunGeneratedInstaller(const CAvailableApplicationInfo &AppInfo, LPCWSTR Archive);
|
ExtractAndRunGeneratedInstaller(const CAvailableApplicationInfo &AppInfo, LPCWSTR Archive);
|
||||||
|
HRESULT
|
||||||
|
ExtractArchiveForExecution(PCWSTR pszArchive, const CStringW &PackageName, CStringW &TempDir, CStringW &App);
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
#define CurrentArchitecture L"ppc"
|
#define CurrentArchitecture L"ppc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline HRESULT
|
||||||
|
HResultFromWin32(UINT Error)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(Error);
|
||||||
|
}
|
||||||
|
|
||||||
static inline UINT
|
static inline UINT
|
||||||
ErrorFromHResult(HRESULT hr)
|
ErrorFromHResult(HRESULT hr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1058,10 +1058,8 @@ run:
|
||||||
// run it
|
// run it
|
||||||
if (Info.DLType == DLTYPE_APPLICATION)
|
if (Info.DLType == DLTYPE_APPLICATION)
|
||||||
{
|
{
|
||||||
CStringW app, params;
|
CStringW app, params, tempdir;
|
||||||
SHELLEXECUTEINFOW shExInfo = {0};
|
SHELLEXECUTEINFOW shExInfo = { sizeof(shExInfo), SEE_MASK_NOCLOSEPROCESS, hDlg };
|
||||||
shExInfo.cbSize = sizeof(shExInfo);
|
|
||||||
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
|
||||||
shExInfo.lpVerb = L"open";
|
shExInfo.lpVerb = L"open";
|
||||||
shExInfo.lpFile = Path;
|
shExInfo.lpFile = Path;
|
||||||
shExInfo.lpParameters = L"";
|
shExInfo.lpParameters = L"";
|
||||||
|
@ -1077,6 +1075,16 @@ run:
|
||||||
GetModuleFileNameW(NULL, const_cast<LPWSTR>(shExInfo.lpFile), MAX_PATH);
|
GetModuleFileNameW(NULL, const_cast<LPWSTR>(shExInfo.lpFile), MAX_PATH);
|
||||||
app.ReleaseBuffer();
|
app.ReleaseBuffer();
|
||||||
}
|
}
|
||||||
|
else if (Info.IType == INSTALLER_EXEINZIP)
|
||||||
|
{
|
||||||
|
HRESULT hr = ExtractArchiveForExecution(Path, Info.szPackageName, tempdir, app);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
ShowLastError(hDlg, FALSE, hr);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
shExInfo.lpFile = app;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Do we want to log installer status? */
|
/* FIXME: Do we want to log installer status? */
|
||||||
WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, Info.szName);
|
WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, Info.szName);
|
||||||
|
@ -1102,6 +1110,11 @@ run:
|
||||||
{
|
{
|
||||||
ShowLastError(hMainWnd, FALSE, GetLastError());
|
ShowLastError(hMainWnd, FALSE, GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tempdir.IsEmpty())
|
||||||
|
{
|
||||||
|
DeleteDirectoryTree(tempdir, hDlg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -1117,8 +1130,8 @@ end:
|
||||||
if (bCancelled || (SettingsInfo.bDelInstaller && Info.DLType == DLTYPE_APPLICATION))
|
if (bCancelled || (SettingsInfo.bDelInstaller && Info.DLType == DLTYPE_APPLICATION))
|
||||||
{
|
{
|
||||||
// Don't delete .zip/.cab files so the user can extract from them
|
// Don't delete .zip/.cab files so the user can extract from them
|
||||||
if (bCancelled || Info.IType == INSTALLER_GENERATE || !OpensWithExplorer(Path) ||
|
if (bCancelled || Info.IType == INSTALLER_GENERATE || Info.IType == INSTALLER_EXEINZIP ||
|
||||||
HIBYTE(ClassifyFile(Path)) != PERCEIVED_TYPE_COMPRESSED)
|
!OpensWithExplorer(Path) || HIBYTE(ClassifyFile(Path)) != PERCEIVED_TYPE_COMPRESSED)
|
||||||
{
|
{
|
||||||
DeleteFileW(Path);
|
DeleteFileW(Path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,9 +331,7 @@ ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
CStringW Directory;
|
CAppDB db(CAppDB::GetDefaultPath());
|
||||||
GetStorageDirectory(Directory);
|
|
||||||
CAppDB db(Directory);
|
|
||||||
|
|
||||||
BOOL bAppwizMode = (argc > 1 && MatchCmdOption(argv[1], CMD_KEY_APPWIZ));
|
BOOL bAppwizMode = (argc > 1 && MatchCmdOption(argv[1], CMD_KEY_APPWIZ));
|
||||||
if (!bAppwizMode)
|
if (!bAppwizMode)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue