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

commit 104ef25fcc8c9859e327e17149d2f7fe8bac1dfe
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Jul 22 12:57:32 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Jul 22 12:57:32 2023 +0900

    [ZIPFLDR][BOOTDATA] Support UTF-8 Zip packing (#5450)
    
    New ReactOS can zip/unzip files and folders in UTF-8 filenames.
    You can also choose the codepage of filenames to zip/unzip via
    the ZipCodePage / UnZipCodePage registry values on the registry
    key HKEY_CURRENT_USER\Software\ReactOS.
    
    Windows 8 or later also support UTF-8 zipped folders.
    You can also use 3rd party software to zip/unzip in older Windows.
    
    - Use <atlconv.h> for string conversion.
    - Use zipOpenNewFileInZip4_64 instead of zipOpenNewFileInZip3_64,
      and then add MINIZIP_UTF8_FLAG flag.
    - Set the filenames in UTF-8 by using CP_UTF8 codepage.
    - Codepage is user selectable via registry settings.
    
    CORE-16668
---
 boot/bootdata/hivedef.inf               |  4 ++++
 dll/shellext/zipfldr/CZipCreator.cpp    | 20 ++++++++------------
 dll/shellext/zipfldr/CZipEnumerator.hpp |  8 +++++---
 dll/shellext/zipfldr/precomp.h          |  7 +++----
 dll/shellext/zipfldr/zipfldr.cpp        | 29 ++++++++++++++++++++++-------
 5 files changed, 42 insertions(+), 26 deletions(-)

diff --git a/boot/bootdata/hivedef.inf b/boot/bootdata/hivedef.inf
index 484c4cbbb7b..2b7a2c53c47 100644
--- a/boot/bootdata/hivedef.inf
+++ b/boot/bootdata/hivedef.inf
@@ -1978,6 +1978,10 @@ HKCU,"SOFTWARE\Microsoft\Windows 
NT\CurrentVersion\AppCompatFlags\Layers\WINXP",
 HKCU,"SOFTWARE\Microsoft\Windows 
NT\CurrentVersion\AppCompatFlags\Layers\WINXP","SPMajorVersion",0x00010001,0x00000001
 HKCU,"SOFTWARE\Microsoft\Windows 
NT\CurrentVersion\AppCompatFlags\Layers\WINXP","SPMinorVersion",0x00010001,0x00000000
 
+; Zip/UnZip codepages
+HKCU,"SOFTWARE\ReactOS","ZipCodePage",0x00000000,"65001" ; CP_UTF8
+HKCU,"SOFTWARE\ReactOS","UnZipCodePage",0x00000000,"0"   ; CP_ACP
+
 ; DEBUG: Windows Messages SPY configuration
 HKCU,"SOFTWARE\ReactOS\Debug","SpyInclude",0x00020000,"INCLUDEALL"
 ;HKCU,"SOFTWARE\ReactOS\Debug","SpyExclude",0x00020000,""
diff --git a/dll/shellext/zipfldr/CZipCreator.cpp 
b/dll/shellext/zipfldr/CZipCreator.cpp
index 00f44932b42..fdae3f3cf59 100644
--- a/dll/shellext/zipfldr/CZipCreator.cpp
+++ b/dll/shellext/zipfldr/CZipCreator.cpp
@@ -3,7 +3,7 @@
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Create a zip file
  * COPYRIGHT:   Copyright 2019 Mark Jansen ([email protected])
- *              Copyright 2019 Katayama Hirofumi MZ 
([email protected])
+ *              Copyright 2019-2023 Katayama Hirofumi MZ 
([email protected])
  */
 
 #include "precomp.h"
@@ -34,13 +34,6 @@ static CStringW DoGetZipName(PCWSTR filename)
     return ret;
 }
 
-static CStringA DoGetAnsiName(PCWSTR filename)
-{
-    CHAR buf[MAX_PATH];
-    WideCharToMultiByte(CP_ACP, 0, filename, -1, buf, _countof(buf), NULL, 
NULL);
-    return buf;
-}
-
 static CStringW DoGetBaseName(PCWSTR filename)
 {
     WCHAR szBaseName[MAX_PATH];
@@ -51,7 +44,7 @@ static CStringW DoGetBaseName(PCWSTR filename)
 }
 
 static CStringA
-DoGetNameInZip(const CStringW& basename, const CStringW& filename)
+DoGetNameInZip(const CStringW& basename, const CStringW& filename, UINT 
nCodePage)
 {
     CStringW basenameI = basename, filenameI = filename;
     basenameI.MakeUpper();
@@ -65,7 +58,7 @@ DoGetNameInZip(const CStringW& basename, const CStringW& 
filename)
 
     ret.Replace(L'\\', L'/');
 
-    return DoGetAnsiName(ret);
+    return CStringA(CW2AEX<MAX_PATH>(ret, nCodePage));
 }
 
 static BOOL
@@ -279,6 +272,7 @@ unsigned CZipCreatorImpl::JustDoIt()
 
     int err = 0;
     CStringW strTarget, strBaseName = DoGetBaseName(m_items[0]);
+    UINT nCodePage = GetZipCodePage(FALSE);
     for (INT iFile = 0; iFile < files.GetSize(); ++iFile)
     {
         const CStringW& strFile = files[iFile];
@@ -298,8 +292,8 @@ unsigned CZipCreatorImpl::JustDoIt()
             // TODO: crc = ...;
         }
 
-        CStringA strNameInZip = DoGetNameInZip(strBaseName, strFile);
-        err = zipOpenNewFileInZip3_64(zf,
+        CStringA strNameInZip = DoGetNameInZip(strBaseName, strFile, 
nCodePage);
+        err = zipOpenNewFileInZip4_64(zf,
                                       strNameInZip,
                                       &zi,
                                       NULL,
@@ -315,6 +309,8 @@ unsigned CZipCreatorImpl::JustDoIt()
                                       Z_DEFAULT_STRATEGY,
                                       password,
                                       crc,
+                                      MINIZIP_COMPATIBLE_VERSION,
+                                      (nCodePage == CP_UTF8 ? 
MINIZIP_UTF8_FLAG : 0),
                                       zip64);
         if (err)
         {
diff --git a/dll/shellext/zipfldr/CZipEnumerator.hpp 
b/dll/shellext/zipfldr/CZipEnumerator.hpp
index 3e7037c1e5d..81752116ea2 100644
--- a/dll/shellext/zipfldr/CZipEnumerator.hpp
+++ b/dll/shellext/zipfldr/CZipEnumerator.hpp
@@ -12,9 +12,11 @@ private:
     CComPtr<IZip> m_Zip;
     bool m_First;
     CAtlList<CStringW> m_Returned;
+    UINT m_nCodePage;
 public:
     CZipEnumerator()
-        :m_First(true)
+        : m_First(true)
+        , m_nCodePage(GetZipCodePage(TRUE))
     {
     }
 
@@ -92,9 +94,9 @@ public:
             nameA.Replace('\\', '/');
 
             if (info.flag & MINIZIP_UTF8_FLAG)
-                Utf8ToWide(nameA, name);
+                name = CA2WEX<MAX_PATH>(nameA, CP_UTF8);
             else
-                name = CStringW(nameA);
+                name = CA2WEX<MAX_PATH>(nameA, m_nCodePage);
         }
         return err == UNZ_OK;
     }
diff --git a/dll/shellext/zipfldr/precomp.h b/dll/shellext/zipfldr/precomp.h
index 7eaab9c3738..448e8ad5528 100644
--- a/dll/shellext/zipfldr/precomp.h
+++ b/dll/shellext/zipfldr/precomp.h
@@ -11,6 +11,7 @@
 #include <atlbase.h>
 #include <atlcom.h>
 #include <atlcoll.h>
+#include <atlconv.h>
 #include <atlstr.h>
 #include <ui/rosdlgs.h>
 #include <shlwapi.h>
@@ -21,8 +22,6 @@
 #include <reactos/debug.h>
 #include <shellutils.h>
 
-void Utf8ToWide(const CStringA& strUtf8, CStringW& strWide);
-
 #define EXTRACT_VERBA "extract"
 #define EXTRACT_VERBW L"extract"
 
@@ -36,10 +35,10 @@ EXTERN_C const GUID CLSID_ZipFolderExtractAllCommand;
 
 extern LONG g_ModuleRefCnt;
 
-
+UINT GetZipCodePage(BOOL bUnZip);
 WCHAR* guid2string(REFCLSID iid);
 
-
+#define MINIZIP_COMPATIBLE_VERSION 36
 #define MINIZIP_PASSWORD_FLAG   1
 #define MINIZIP_UTF8_FLAG       (1 << 11)
 
diff --git a/dll/shellext/zipfldr/zipfldr.cpp b/dll/shellext/zipfldr/zipfldr.cpp
index 07fcc3a01b5..df2079e1827 100644
--- a/dll/shellext/zipfldr/zipfldr.cpp
+++ b/dll/shellext/zipfldr/zipfldr.cpp
@@ -48,13 +48,6 @@ static void init_zlib()
     fill_win32_filefunc64W(&g_FFunc);
 }
 
-void Utf8ToWide(const CStringA& strUtf8, CStringW& strWide)
-{
-    INT cchWide = MultiByteToWideChar(CP_UTF8, 0, strUtf8, -1, NULL, 0);
-    MultiByteToWideChar(CP_UTF8, 0, strUtf8, -1, strWide.GetBuffer(cchWide), 
cchWide);
-    strWide.ReleaseBuffer();
-}
-
 static BOOL
 CreateEmptyFile(PCWSTR pszFile)
 {
@@ -94,6 +87,28 @@ GetDefaultUserSendTo(PWSTR pszPath)
                             SHGFP_TYPE_DEFAULT, pszPath);
 }
 
+UINT GetZipCodePage(BOOL bUnZip)
+{
+    WCHAR szValue[16];
+    DWORD dwType, cbValue = sizeof(szValue);
+    UINT nDefaultCodePage = (bUnZip ? CP_ACP : CP_UTF8);
+
+    LONG error = SHGetValueW(HKEY_CURRENT_USER, L"Software\\ReactOS",
+                             (bUnZip ? L"UnZipCodePage" : L"ZipCodePage"),
+                             &dwType, szValue, &cbValue);
+    if (error != ERROR_SUCCESS)
+        return nDefaultCodePage;
+
+    if (cbValue == sizeof(DWORD) && (dwType == REG_DWORD || dwType == 
REG_BINARY))
+        return *(DWORD*)szValue;
+
+    if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
+        return nDefaultCodePage;
+
+    szValue[_countof(szValue) - 1] = UNICODE_NULL;
+    return (UINT)wcstol(szValue, NULL, 0);
+}
+
 EXTERN_C
 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
 {

Reply via email to