From 7dc7b866b110a9a4831221c304f7dda00ccaeb93 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Thu, 20 Mar 2025 14:32:07 +0100 Subject: [PATCH] [RAPPS] Don't delete downloaded ZIP/CAB even if configured to (#7791) --- base/applications/rapps/geninst.cpp | 13 ++++++- base/applications/rapps/include/misc.h | 4 ++ base/applications/rapps/loaddlg.cpp | 9 ++++- base/applications/rapps/misc.cpp | 53 ++++++++++++++++++++++++++ base/applications/rapps/winmain.cpp | 2 +- 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/base/applications/rapps/geninst.cpp b/base/applications/rapps/geninst.cpp index d5746d5199a..9d00156f55c 100644 --- a/base/applications/rapps/geninst.cpp +++ b/base/applications/rapps/geninst.cpp @@ -47,6 +47,17 @@ enum { UNOP_EMPTYREGKEY = 'k', }; +BOOL IsZipFile(PCWSTR Path) +{ + zlib_filefunc64_def zff; + fill_win32_filefunc64W(&zff); + unzFile hzf = unzOpen2_64(Path, &zff); + if (!hzf) + return FALSE; + unzClose(hzf); + return TRUE; +} + static int ExtractFilesFromZip(LPCWSTR Archive, const CStringW &OutputDir, EXTRACTCALLBACK Callback, void *Cookie) @@ -491,7 +502,7 @@ ExtractAndInstallThread(LPVOID Parameter) if (!Info.Error) { - BOOL isCab = SplitFileAndDirectory(Archive).Right(4).CompareNoCase(L".cab") == 0; + BOOL isCab = LOBYTE(ClassifyFile(tempdir)) == 'C'; Info.Error = isCab ? ExtractCab(Archive, tempdir, ExtractCallback, &Info) : ExtractZip(Archive, tempdir, ExtractCallback, &Info); } diff --git a/base/applications/rapps/include/misc.h b/base/applications/rapps/include/misc.h index 6e8b56ffb14..6e7814b8cee 100644 --- a/base/applications/rapps/include/misc.h +++ b/base/applications/rapps/include/misc.h @@ -35,6 +35,10 @@ VOID ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem, POINT *Point = NULL); VOID EmulateDialogReposition(HWND hwnd); +UINT +ClassifyFile(PCWSTR Path); +BOOL +OpensWithExplorer(PCWSTR Path); BOOL StartProcess(const CStringW &Path, BOOL Wait); BOOL diff --git a/base/applications/rapps/loaddlg.cpp b/base/applications/rapps/loaddlg.cpp index 21b7b88d1fc..8d51fe78f8c 100644 --- a/base/applications/rapps/loaddlg.cpp +++ b/base/applications/rapps/loaddlg.cpp @@ -1115,7 +1115,14 @@ end: if (bTempfile) { if (bCancelled || (SettingsInfo.bDelInstaller && Info.DLType == DLTYPE_APPLICATION)) - DeleteFileW(Path); + { + // Don't delete .zip/.cab files so the user can extract from them + if (bCancelled || Info.IType == INSTALLER_GENERATE || !OpensWithExplorer(Path) || + HIBYTE(ClassifyFile(Path)) != PERCEIVED_TYPE_COMPRESSED) + { + DeleteFileW(Path); + } + } } SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_FINISHED, 0); diff --git a/base/applications/rapps/misc.cpp b/base/applications/rapps/misc.cpp index e8d9e439177..0965cc945d0 100644 --- a/base/applications/rapps/misc.cpp +++ b/base/applications/rapps/misc.cpp @@ -119,6 +119,59 @@ ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem, POINT } } +extern BOOL IsZipFile(PCWSTR Path); + +UINT +ClassifyFile(PCWSTR Path) +{ + const UINT share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + HANDLE hFile = CreateFileW(Path, GENERIC_READ, share, NULL, OPEN_EXISTING, 0, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + BYTE buf[8]; + DWORD io; + if (!ReadFile(hFile, buf, sizeof(buf), &io, NULL) || io != sizeof(buf)) + buf[0] = 0; + CloseHandle(hFile); + + if (buf[0] == 0xD0 && buf[1] == 0xCF && buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && buf[6] == 0x1A && buf[7] == 0xE1) + { + return MAKEWORD('M', PERCEIVED_TYPE_APPLICATION); // MSI + } + if (buf[0] == 'M' || buf[0] == 'Z') + { + SHFILEINFO shfi; + if (SHGetFileInfoW(Path, 0, &shfi, sizeof(shfi), SHGFI_EXETYPE)) + return MAKEWORD('E', PERCEIVED_TYPE_APPLICATION); + } + if (buf[0] == 'M' && buf[1] == 'S' && buf[2] == 'C' && buf[3] == 'F') + { + return MAKEWORD('C', PERCEIVED_TYPE_COMPRESSED); // CAB + } + } + + if (IsZipFile(Path)) // .zip last because we want to return SFX.exe with higher priority + { + return MAKEWORD('Z', PERCEIVED_TYPE_COMPRESSED); + } + return PERCEIVED_TYPE_UNKNOWN; +} + +BOOL +OpensWithExplorer(PCWSTR Path) +{ + WCHAR szCmd[MAX_PATH * 2]; + DWORD cch = _countof(szCmd); + PCWSTR pszExt = PathFindExtensionW(Path); + HRESULT hr = AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN | ASSOCF_NOTRUNCATE, + ASSOCSTR_COMMAND, pszExt, NULL, szCmd, &cch); + if (SUCCEEDED(hr) && StrStrIW(szCmd, L" zipfldr.dll,")) // .zip + return TRUE; + PathRemoveArgsW(szCmd); + return SUCCEEDED(hr) && !StrCmpIW(PathFindFileNameW(szCmd), L"explorer.exe"); // .cab +} + BOOL StartProcess(const CStringW &Path, BOOL Wait) { diff --git a/base/applications/rapps/winmain.cpp b/base/applications/rapps/winmain.cpp index 70ce317a468..e36ac0db5ab 100644 --- a/base/applications/rapps/winmain.cpp +++ b/base/applications/rapps/winmain.cpp @@ -16,7 +16,7 @@ LPCWSTR szWindowClass = MAINWINDOWCLASSNAME; LONG g_Busy = 0; -HWND hMainWnd; +HWND hMainWnd = NULL; HINSTANCE hInst; SETTINGS_INFO SettingsInfo;