https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fd441aaae722db784b1f5…
commit fd441aaae722db784b1f55dd3e0f1faf1d8bcf70
Author: Stanislav Motylkov <x86corez(a)gmail.com>
AuthorDate: Tue Oct 5 21:54:39 2021 +0300
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
CommitDate: Wed Oct 6 14:36:48 2021 +0300
[ZIPFLDR] Refactor extraction function
Add separate function for a single file extraction.
CORE-17796
---
dll/shellext/zipfldr/CZipExtract.cpp | 362 +++++++++++++++++++----------------
dll/shellext/zipfldr/precomp.h | 10 +
2 files changed, 206 insertions(+), 166 deletions(-)
diff --git a/dll/shellext/zipfldr/CZipExtract.cpp b/dll/shellext/zipfldr/CZipExtract.cpp
index bd7dbb7f005..8e2b9fa3bb4 100644
--- a/dll/shellext/zipfldr/CZipExtract.cpp
+++ b/dll/shellext/zipfldr/CZipExtract.cpp
@@ -344,6 +344,189 @@ public:
PropertySheetW(&psh);
}
+ eZipExtractError ExtractSingle(
+ HWND hDlg,
+ LPCSTR FullPath,
+ bool is_dir,
+ unz_file_info64* Info,
+ CStringA Name,
+ CStringA Password,
+ bool* bOverwriteAll,
+ const bool* bCancel,
+ int* ErrorCode
+ )
+ {
+ int err;
+ BYTE Buffer[2048];
+ DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE :
SHPPFW_IGNOREFILENAME);
+ HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags);
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ *ErrorCode = hr;
+ return eDirectoryError;
+ }
+ if (is_dir)
+ return eNoError;
+
+ if (Info->flag & MINIZIP_PASSWORD_FLAG)
+ {
+ eZipPasswordResponse Response = eAccept;
+ do
+ {
+ /* If there is a password set, try it */
+ if (!Password.IsEmpty())
+ {
+ err = unzOpenCurrentFilePassword(uf, Password);
+ if (err == UNZ_OK)
+ {
+ /* Try to read some bytes, because unzOpenCurrentFilePassword
does not return failure */
+ char Buf[10];
+ err = unzReadCurrentFile(uf, Buf, sizeof(Buf));
+ unzCloseCurrentFile(uf);
+ if (err >= UNZ_OK)
+ {
+ /* 're'-open the file so that we can begin to extract
*/
+ err = unzOpenCurrentFilePassword(uf, Password);
+ break;
+ }
+ }
+ }
+ Response = _CZipAskPassword(hDlg, Name, Password);
+ } while (Response == eAccept);
+
+ if (Response == eSkip)
+ {
+ return eNoError;
+ }
+ else if (Response == eAbort)
+ {
+ return eExtractAbort;
+ }
+ }
+ else
+ {
+ err = unzOpenCurrentFile(uf);
+ }
+
+ if (err != UNZ_OK)
+ {
+ DPRINT1("ERROR, unzOpenCurrentFilePassword: 0x%x\n", err);
+ *ErrorCode = err;
+ return eOpenError;
+ }
+
+ HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_FILE_EXISTS)
+ {
+ bool bOverwrite = *bOverwriteAll;
+ if (!*bOverwriteAll)
+ {
+ eZipConfirmResponse Result = _CZipAskReplace(hDlg, FullPath);
+ switch (Result)
+ {
+ case eYesToAll:
+ *bOverwriteAll = true;
+ /* fall through */
+ case eYes:
+ bOverwrite = true;
+ break;
+ case eNo:
+ break;
+ case eCancel:
+ unzCloseCurrentFile(uf);
+ return eExtractAbort;
+ }
+ }
+
+ if (bOverwrite)
+ {
+ hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ dwErr = GetLastError();
+ }
+ }
+ else
+ {
+ unzCloseCurrentFile(uf);
+ return eNoError;
+ }
+ }
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ unzCloseCurrentFile(uf);
+ DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr,
*bOverwriteAll ? "Y" : "N");
+ *ErrorCode = dwErr;
+ return eFileError;
+ }
+ }
+
+ do
+ {
+ if (*bCancel)
+ {
+ CloseHandle(hFile);
+ BOOL deleteResult = DeleteFileA(FullPath);
+ if (!deleteResult)
+ DPRINT1("ERROR, DeleteFileA: 0x%x\n", GetLastError());
+ return eExtractAbort;
+ }
+
+ err = unzReadCurrentFile(uf, Buffer, sizeof(Buffer));
+
+ if (err < 0)
+ {
+ DPRINT1("ERROR, unzReadCurrentFile: 0x%x\n", err);
+ break;
+ }
+ else if (err > 0)
+ {
+ DWORD dwWritten;
+ if (!WriteFile(hFile, Buffer, err, &dwWritten, NULL))
+ {
+ DPRINT1("ERROR, WriteFile: 0x%x\n", GetLastError());
+ break;
+ }
+ if (dwWritten != (DWORD)err)
+ {
+ DPRINT1("ERROR, WriteFile: dwWritten:%d err:%d\n",
dwWritten, err);
+ break;
+ }
+ }
+
+ } while (err > 0);
+
+ /* Update Filetime */
+ FILETIME LocalFileTime;
+ DosDateTimeToFileTime((WORD)(Info->dosDate >> 16),
(WORD)Info->dosDate, &LocalFileTime);
+ FILETIME FileTime;
+ LocalFileTimeToFileTime(&LocalFileTime, &FileTime);
+ SetFileTime(hFile, &FileTime, &FileTime, &FileTime);
+
+ /* Done */
+ CloseHandle(hFile);
+
+ if (err)
+ {
+ unzCloseCurrentFile(uf);
+ DPRINT1("ERROR, unzReadCurrentFile2: 0x%x\n", err);
+ *ErrorCode = err;
+ return eUnpackError;
+ }
+ else
+ {
+ err = unzCloseCurrentFile(uf);
+ if (err != UNZ_OK)
+ {
+ DPRINT1("ERROR(non-fatal), unzCloseCurrentFile: 0x%x\n", err);
+ }
+ }
+ return eNoError;
+ }
+
bool Extract(HWND hDlg, HWND hProgress, const bool* bCancel)
{
unz_global_info64 gi;
@@ -368,7 +551,6 @@ public:
Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry);
Progress.SendMessage(PBM_SETPOS, 0, 0);
- BYTE Buffer[2048];
CStringA BaseDirectory = m_Directory;
CStringA Name;
CStringA Password = m_Password;
@@ -389,176 +571,24 @@ public:
PathCombineA(CombinedPath, BaseDirectory, Name);
CStringA FullPath = CombinedPath;
FullPath.Replace('/', '\\'); /* SHPathPrepareForWriteA
does not handle '/' */
- DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE :
SHPPFW_IGNOREFILENAME);
- HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags);
- if (FAILED_UNEXPECTEDLY(hr))
+ eZipExtractError Result = ExtractSingle(hDlg, FullPath, is_dir, &Info,
Name, Password, &bOverwriteAll, bCancel, &err);
+ if (Result != eDirectoryError)
+ CurrentFile++;
+ switch (Result)
{
- Close();
- return false;
- }
- CurrentFile++;
- if (is_dir)
- continue;
-
- if (Info.flag & MINIZIP_PASSWORD_FLAG)
- {
- eZipPasswordResponse Response = eAccept;
- do
- {
- /* If there is a password set, try it */
- if (!Password.IsEmpty())
- {
- err = unzOpenCurrentFilePassword(uf, Password);
- if (err == UNZ_OK)
- {
- /* Try to read some bytes, because unzOpenCurrentFilePassword
does not return failure */
- char Buf[10];
- err = unzReadCurrentFile(uf, Buf, sizeof(Buf));
- unzCloseCurrentFile(uf);
- if (err >= UNZ_OK)
- {
- /* 're'-open the file so that we can begin to
extract */
- err = unzOpenCurrentFilePassword(uf, Password);
- break;
- }
- }
- }
- Response = _CZipAskPassword(hDlg, Name, Password);
- } while (Response == eAccept);
-
- if (Response == eSkip)
- {
- Progress.SendMessage(PBM_SETPOS, CurrentFile, 0);
- continue;
- }
- else if (Response == eAbort)
- {
- Close();
- return false;
- }
- }
- else
- {
- err = unzOpenCurrentFile(uf);
- }
-
- if (err != UNZ_OK)
- {
- DPRINT1("ERROR, unzOpenCurrentFilePassword: 0x%x\n", err);
- Close();
- return false;
- }
-
- HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- {
- DWORD dwErr = GetLastError();
- if (dwErr == ERROR_FILE_EXISTS)
- {
- bool bOverwrite = bOverwriteAll;
- if (!bOverwriteAll)
- {
- eZipConfirmResponse Result = _CZipAskReplace(hDlg, FullPath);
- switch (Result)
- {
- case eYesToAll:
- bOverwriteAll = true;
- case eYes:
- bOverwrite = true;
- break;
- case eNo:
- break;
- case eCancel:
- unzCloseCurrentFile(uf);
- Close();
- return false;
- }
- }
-
- if (bOverwrite)
- {
- hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- {
- dwErr = GetLastError();
- }
- }
- else
- {
- unzCloseCurrentFile(uf);
- continue;
- }
- }
- if (hFile == INVALID_HANDLE_VALUE)
- {
- unzCloseCurrentFile(uf);
- DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr,
bOverwriteAll ? "Y" : "N");
- Close();
- return false;
- }
- }
+ case eNoError:
+ break;
- do
- {
- if (*bCancel)
- {
- CloseHandle(hFile);
- BOOL deleteResult = DeleteFileA(FullPath);
- if (deleteResult == 0)
- DPRINT1("ERROR, DeleteFileA: 0x%x\n", GetLastError());
+ case eExtractAbort:
+ case eDirectoryError:
+ case eFileError:
+ case eOpenError:
+ case eUnpackError:
Close();
return false;
- }
-
- err = unzReadCurrentFile(uf, Buffer, sizeof(Buffer));
-
- if (err < 0)
- {
- DPRINT1("ERROR, unzReadCurrentFile: 0x%x\n", err);
- break;
- }
- else if (err > 0)
- {
- DWORD dwWritten;
- if (!WriteFile(hFile, Buffer, err, &dwWritten, NULL))
- {
- DPRINT1("ERROR, WriteFile: 0x%x\n", GetLastError());
- break;
- }
- if (dwWritten != (DWORD)err)
- {
- DPRINT1("ERROR, WriteFile: dwWritten:%d err:%d\n",
dwWritten, err);
- break;
- }
- }
-
- } while (err > 0);
-
- /* Update Filetime */
- FILETIME LocalFileTime;
- DosDateTimeToFileTime((WORD)(Info.dosDate >> 16), (WORD)Info.dosDate,
&LocalFileTime);
- FILETIME FileTime;
- LocalFileTimeToFileTime(&LocalFileTime, &FileTime);
- SetFileTime(hFile, &FileTime, &FileTime, &FileTime);
-
- /* Done */
- CloseHandle(hFile);
-
- if (err)
- {
- unzCloseCurrentFile(uf);
- DPRINT1("ERROR, unzReadCurrentFile2: 0x%x\n", err);
- Close();
- return false;
- }
- else
- {
- err = unzCloseCurrentFile(uf);
- if (err != UNZ_OK)
- {
- DPRINT1("ERROR(non-fatal), unzCloseCurrentFile: 0x%x\n",
err);
- }
}
+ if (Result == eNoError && is_dir)
+ continue;
Progress.SendMessage(PBM_SETPOS, CurrentFile, 0);
}
diff --git a/dll/shellext/zipfldr/precomp.h b/dll/shellext/zipfldr/precomp.h
index b228624b8dc..f21ce4873d5 100644
--- a/dll/shellext/zipfldr/precomp.h
+++ b/dll/shellext/zipfldr/precomp.h
@@ -76,6 +76,16 @@ enum eZipConfirmResponse
eZipConfirmResponse _CZipAskReplace(HWND hDlg, const char* FullPath);
+enum eZipExtractError
+{
+ eNoError,
+ eExtractAbort,
+ eDirectoryError,
+ eFileError,
+ eOpenError,
+ eUnpackError,
+};
+
#include "CZipEnumerator.hpp"
#include "CZipFolder.hpp"
#include "CZipCreator.hpp"