https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fd441aaae722db784b1f55...
commit fd441aaae722db784b1f55dd3e0f1faf1d8bcf70 Author: Stanislav Motylkov x86corez@gmail.com AuthorDate: Tue Oct 5 21:54:39 2021 +0300 Commit: Stanislav Motylkov x86corez@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"