[ZIPFLDR] Refactor extraction function

Add separate function for a single file extraction.

CORE-17796
This commit is contained in:
Stanislav Motylkov 2021-10-05 21:54:39 +03:00
parent e6fd41d078
commit fd441aaae7
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92
2 changed files with 207 additions and 167 deletions

View file

@ -344,63 +344,31 @@ public:
PropertySheetW(&psh); PropertySheetW(&psh);
} }
bool Extract(HWND hDlg, HWND hProgress, const bool* bCancel) eZipExtractError ExtractSingle(
HWND hDlg,
LPCSTR FullPath,
bool is_dir,
unz_file_info64* Info,
CStringA Name,
CStringA Password,
bool* bOverwriteAll,
const bool* bCancel,
int* ErrorCode
)
{ {
unz_global_info64 gi; int err;
uf = unzOpen2_64(m_Filename.GetString(), &g_FFunc);
int err = unzGetGlobalInfo64(uf, &gi);
if (err != UNZ_OK)
{
DPRINT1("ERROR, unzGetGlobalInfo64: 0x%x\n", err);
Close();
return false;
}
CZipEnumerator zipEnum;
if (!zipEnum.initialize(this))
{
DPRINT1("ERROR, zipEnum.initialize\n");
Close();
return false;
}
CWindow Progress(hProgress);
Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry);
Progress.SendMessage(PBM_SETPOS, 0, 0);
BYTE Buffer[2048]; BYTE Buffer[2048];
CStringA BaseDirectory = m_Directory;
CStringA Name;
CStringA Password = m_Password;
unz_file_info64 Info;
int CurrentFile = 0;
bool bOverwriteAll = false;
while (zipEnum.next(Name, Info))
{
if (*bCancel)
{
Close();
return false;
}
bool is_dir = Name.GetLength() > 0 && Name[Name.GetLength()-1] == '/';
char CombinedPath[MAX_PATH * 2] = { 0 };
PathCombineA(CombinedPath, BaseDirectory, Name);
CStringA FullPath = CombinedPath;
FullPath.Replace('/', '\\'); /* SHPathPrepareForWriteA does not handle '/' */
DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE : SHPPFW_IGNOREFILENAME); DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE : SHPPFW_IGNOREFILENAME);
HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags); HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
{ {
Close(); *ErrorCode = hr;
return false; return eDirectoryError;
} }
CurrentFile++;
if (is_dir) if (is_dir)
continue; return eNoError;
if (Info.flag & MINIZIP_PASSWORD_FLAG) if (Info->flag & MINIZIP_PASSWORD_FLAG)
{ {
eZipPasswordResponse Response = eAccept; eZipPasswordResponse Response = eAccept;
do do
@ -428,13 +396,11 @@ public:
if (Response == eSkip) if (Response == eSkip)
{ {
Progress.SendMessage(PBM_SETPOS, CurrentFile, 0); return eNoError;
continue;
} }
else if (Response == eAbort) else if (Response == eAbort)
{ {
Close(); return eExtractAbort;
return false;
} }
} }
else else
@ -445,8 +411,8 @@ public:
if (err != UNZ_OK) if (err != UNZ_OK)
{ {
DPRINT1("ERROR, unzOpenCurrentFilePassword: 0x%x\n", err); DPRINT1("ERROR, unzOpenCurrentFilePassword: 0x%x\n", err);
Close(); *ErrorCode = err;
return false; return eOpenError;
} }
HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
@ -455,14 +421,15 @@ public:
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
if (dwErr == ERROR_FILE_EXISTS) if (dwErr == ERROR_FILE_EXISTS)
{ {
bool bOverwrite = bOverwriteAll; bool bOverwrite = *bOverwriteAll;
if (!bOverwriteAll) if (!*bOverwriteAll)
{ {
eZipConfirmResponse Result = _CZipAskReplace(hDlg, FullPath); eZipConfirmResponse Result = _CZipAskReplace(hDlg, FullPath);
switch (Result) switch (Result)
{ {
case eYesToAll: case eYesToAll:
bOverwriteAll = true; *bOverwriteAll = true;
/* fall through */
case eYes: case eYes:
bOverwrite = true; bOverwrite = true;
break; break;
@ -470,8 +437,7 @@ public:
break; break;
case eCancel: case eCancel:
unzCloseCurrentFile(uf); unzCloseCurrentFile(uf);
Close(); return eExtractAbort;
return false;
} }
} }
@ -486,15 +452,15 @@ public:
else else
{ {
unzCloseCurrentFile(uf); unzCloseCurrentFile(uf);
continue; return eNoError;
} }
} }
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
{ {
unzCloseCurrentFile(uf); unzCloseCurrentFile(uf);
DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr, bOverwriteAll ? "Y" : "N"); DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr, *bOverwriteAll ? "Y" : "N");
Close(); *ErrorCode = dwErr;
return false; return eFileError;
} }
} }
@ -504,10 +470,9 @@ public:
{ {
CloseHandle(hFile); CloseHandle(hFile);
BOOL deleteResult = DeleteFileA(FullPath); BOOL deleteResult = DeleteFileA(FullPath);
if (deleteResult == 0) if (!deleteResult)
DPRINT1("ERROR, DeleteFileA: 0x%x\n", GetLastError()); DPRINT1("ERROR, DeleteFileA: 0x%x\n", GetLastError());
Close(); return eExtractAbort;
return false;
} }
err = unzReadCurrentFile(uf, Buffer, sizeof(Buffer)); err = unzReadCurrentFile(uf, Buffer, sizeof(Buffer));
@ -536,7 +501,7 @@ public:
/* Update Filetime */ /* Update Filetime */
FILETIME LocalFileTime; FILETIME LocalFileTime;
DosDateTimeToFileTime((WORD)(Info.dosDate >> 16), (WORD)Info.dosDate, &LocalFileTime); DosDateTimeToFileTime((WORD)(Info->dosDate >> 16), (WORD)Info->dosDate, &LocalFileTime);
FILETIME FileTime; FILETIME FileTime;
LocalFileTimeToFileTime(&LocalFileTime, &FileTime); LocalFileTimeToFileTime(&LocalFileTime, &FileTime);
SetFileTime(hFile, &FileTime, &FileTime, &FileTime); SetFileTime(hFile, &FileTime, &FileTime, &FileTime);
@ -548,8 +513,8 @@ public:
{ {
unzCloseCurrentFile(uf); unzCloseCurrentFile(uf);
DPRINT1("ERROR, unzReadCurrentFile2: 0x%x\n", err); DPRINT1("ERROR, unzReadCurrentFile2: 0x%x\n", err);
Close(); *ErrorCode = err;
return false; return eUnpackError;
} }
else else
{ {
@ -559,6 +524,71 @@ public:
DPRINT1("ERROR(non-fatal), unzCloseCurrentFile: 0x%x\n", err); DPRINT1("ERROR(non-fatal), unzCloseCurrentFile: 0x%x\n", err);
} }
} }
return eNoError;
}
bool Extract(HWND hDlg, HWND hProgress, const bool* bCancel)
{
unz_global_info64 gi;
uf = unzOpen2_64(m_Filename.GetString(), &g_FFunc);
int err = unzGetGlobalInfo64(uf, &gi);
if (err != UNZ_OK)
{
DPRINT1("ERROR, unzGetGlobalInfo64: 0x%x\n", err);
Close();
return false;
}
CZipEnumerator zipEnum;
if (!zipEnum.initialize(this))
{
DPRINT1("ERROR, zipEnum.initialize\n");
Close();
return false;
}
CWindow Progress(hProgress);
Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry);
Progress.SendMessage(PBM_SETPOS, 0, 0);
CStringA BaseDirectory = m_Directory;
CStringA Name;
CStringA Password = m_Password;
unz_file_info64 Info;
int CurrentFile = 0;
bool bOverwriteAll = false;
while (zipEnum.next(Name, Info))
{
if (*bCancel)
{
Close();
return false;
}
bool is_dir = Name.GetLength() > 0 && Name[Name.GetLength()-1] == '/';
char CombinedPath[MAX_PATH * 2] = { 0 };
PathCombineA(CombinedPath, BaseDirectory, Name);
CStringA FullPath = CombinedPath;
FullPath.Replace('/', '\\'); /* SHPathPrepareForWriteA does not handle '/' */
eZipExtractError Result = ExtractSingle(hDlg, FullPath, is_dir, &Info, Name, Password, &bOverwriteAll, bCancel, &err);
if (Result != eDirectoryError)
CurrentFile++;
switch (Result)
{
case eNoError:
break;
case eExtractAbort:
case eDirectoryError:
case eFileError:
case eOpenError:
case eUnpackError:
Close();
return false;
}
if (Result == eNoError && is_dir)
continue;
Progress.SendMessage(PBM_SETPOS, CurrentFile, 0); Progress.SendMessage(PBM_SETPOS, CurrentFile, 0);
} }

View file

@ -76,6 +76,16 @@ enum eZipConfirmResponse
eZipConfirmResponse _CZipAskReplace(HWND hDlg, const char* FullPath); eZipConfirmResponse _CZipAskReplace(HWND hDlg, const char* FullPath);
enum eZipExtractError
{
eNoError,
eExtractAbort,
eDirectoryError,
eFileError,
eOpenError,
eUnpackError,
};
#include "CZipEnumerator.hpp" #include "CZipEnumerator.hpp"
#include "CZipFolder.hpp" #include "CZipFolder.hpp"
#include "CZipCreator.hpp" #include "CZipCreator.hpp"