https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fd441aaae722db784b1f55dd3e0f1faf1d8bcf70

commit fd441aaae722db784b1f55dd3e0f1faf1d8bcf70
Author:     Stanislav Motylkov <[email protected]>
AuthorDate: Tue Oct 5 21:54:39 2021 +0300
Commit:     Stanislav Motylkov <[email protected]>
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"

Reply via email to