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