https://git.reactos.org/?p=reactos.git;a=commitdiff;h=104ef25fcc8c9859e327e…
commit 104ef25fcc8c9859e327e17149d2f7fe8bac1dfe
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sat Jul 22 12:57:32 2023 +0900
Commit: GitHub <noreply(a)github.com>
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 (mark.jansen(a)reactos.org)
- * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
+ * Copyright 2019-2023 Katayama Hirofumi MZ
(katayama.hirofumi.mz(a)gmail.com)
*/
#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)
{