[ZIPFLDR] Support UTF-8 Zip extraction (#5411)

- Extend some Ansi strings to Wide strings.
- Check the UTF-8 flag (1 << 11). If UTF-8, then use CP_UTF8.
- s/LPCWSTR/PCWSTR/.
- s/LPWSTR/PWSTR/.
CORE-16668
This commit is contained in:
Katayama Hirofumi MZ 2023-07-17 20:12:45 +09:00 committed by GitHub
parent bfadb22da1
commit bf2cec186c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 134 additions and 112 deletions

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Ask the user to replace a file * PURPOSE: Ask the user to replace a file
* COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
@ -10,10 +11,9 @@
class CConfirmReplace : public CDialogImpl<CConfirmReplace> class CConfirmReplace : public CDialogImpl<CConfirmReplace>
{ {
private: private:
CStringA m_Filename; CStringW m_Filename;
public: public:
CConfirmReplace(PCWSTR filename)
CConfirmReplace(const char* filename)
: m_Filename(filename) : m_Filename(filename)
{ {
} }
@ -25,9 +25,9 @@ public:
HICON hIcon = LoadIcon(NULL, IDI_EXCLAMATION); HICON hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
SendDlgItemMessage(IDC_EXCLAMATION_ICON, STM_SETICON, (WPARAM)hIcon); SendDlgItemMessage(IDC_EXCLAMATION_ICON, STM_SETICON, (WPARAM)hIcon);
CStringA message; CStringW message;
message.FormatMessage(IDS_OVERWRITEFILE_TEXT, m_Filename.GetString()); message.FormatMessage(IDS_OVERWRITEFILE_TEXT, m_Filename.GetString());
::SetDlgItemTextA(m_hWnd, IDC_MESSAGE, message); ::SetDlgItemTextW(m_hWnd, IDC_MESSAGE, message);
return TRUE; return TRUE;
} }
@ -50,10 +50,9 @@ public:
END_MSG_MAP() END_MSG_MAP()
}; };
eZipConfirmResponse _CZipAskReplace(HWND hDlg, PCWSTR FullPath)
eZipConfirmResponse _CZipAskReplace(HWND hDlg, PCSTR FullPath)
{ {
PCSTR Filename = PathFindFileNameA(FullPath); PCWSTR Filename = PathFindFileNameW(FullPath);
CConfirmReplace confirm(Filename); CConfirmReplace confirm(Filename);
INT_PTR Result = confirm.DoModal(hDlg); INT_PTR Result = confirm.DoModal(hDlg);
switch (Result) switch (Result)

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: CEnumZipContents * PURPOSE: CEnumZipContents
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
@ -14,14 +15,14 @@ class CEnumZipContents :
private: private:
CZipEnumerator mEnumerator; CZipEnumerator mEnumerator;
DWORD dwFlags; DWORD dwFlags;
CStringA m_Prefix; CStringW m_Prefix;
public: public:
CEnumZipContents() CEnumZipContents()
:dwFlags(0) :dwFlags(0)
{ {
} }
STDMETHODIMP Initialize(IZip* zip, DWORD flags, const char* prefix) STDMETHODIMP Initialize(IZip* zip, DWORD flags, PCWSTR prefix)
{ {
dwFlags = flags; dwFlags = flags;
m_Prefix = prefix; m_Prefix = prefix;
@ -41,7 +42,7 @@ public:
if (celt != 1) if (celt != 1)
return E_FAIL; return E_FAIL;
CStringA name; CStringW name;
bool dir; bool dir;
unz_file_info64 info; unz_file_info64 info;
if (mEnumerator.next_unique(m_Prefix, name, dir, info)) if (mEnumerator.next_unique(m_Prefix, name, dir, info))
@ -55,7 +56,7 @@ public:
} }
STDMETHODIMP Skip(ULONG celt) STDMETHODIMP Skip(ULONG celt)
{ {
CStringA name; CStringW name;
bool dir; bool dir;
unz_file_info64 info; unz_file_info64 info;
while (celt--) while (celt--)
@ -88,7 +89,7 @@ public:
}; };
HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, const char* prefix, REFIID riid, LPVOID * ppvOut) HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, PCWSTR prefix, REFIID riid, LPVOID * ppvOut)
{ {
return ShellObjectCreatorInit<CEnumZipContents>(zip, flags, prefix, riid, ppvOut); return ShellObjectCreatorInit<CEnumZipContents>(zip, flags, prefix, riid, ppvOut);
} }

View file

@ -23,17 +23,17 @@ public:
} }
// *** IExplorerCommand methods *** // *** IExplorerCommand methods ***
STDMETHODIMP GetTitle(IShellItemArray *psiItemArray, LPWSTR *ppszName) STDMETHODIMP GetTitle(IShellItemArray *psiItemArray, PWSTR *ppszName)
{ {
CStringW Title(MAKEINTRESOURCEW(IDS_MENUITEM)); CStringW Title(MAKEINTRESOURCEW(IDS_MENUITEM));
return SHStrDup(Title, ppszName); return SHStrDup(Title, ppszName);
} }
STDMETHODIMP GetIcon(IShellItemArray *psiItemArray, LPWSTR *ppszIcon) STDMETHODIMP GetIcon(IShellItemArray *psiItemArray, PWSTR *ppszIcon)
{ {
CStringW IconName = L"zipfldr.dll,-1"; CStringW IconName = L"zipfldr.dll,-1";
return SHStrDup(IconName, ppszIcon); return SHStrDup(IconName, ppszIcon);
} }
STDMETHODIMP GetToolTip(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip) STDMETHODIMP GetToolTip(IShellItemArray *psiItemArray, PWSTR *ppszInfotip)
{ {
CStringW HelpText(MAKEINTRESOURCEW(IDS_HELPTEXT)); CStringW HelpText(MAKEINTRESOURCEW(IDS_HELPTEXT));
return SHStrDup(HelpText, ppszInfotip); return SHStrDup(HelpText, ppszInfotip);

View file

@ -12,7 +12,7 @@
#include "minizip/iowin32.h" #include "minizip/iowin32.h"
#include <process.h> #include <process.h>
static CStringW DoGetZipName(LPCWSTR filename) static CStringW DoGetZipName(PCWSTR filename)
{ {
WCHAR szPath[MAX_PATH]; WCHAR szPath[MAX_PATH];
StringCbCopyW(szPath, sizeof(szPath), filename); StringCbCopyW(szPath, sizeof(szPath), filename);
@ -34,14 +34,14 @@ static CStringW DoGetZipName(LPCWSTR filename)
return ret; return ret;
} }
static CStringA DoGetAnsiName(LPCWSTR filename) static CStringA DoGetAnsiName(PCWSTR filename)
{ {
CHAR buf[MAX_PATH]; CHAR buf[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, filename, -1, buf, _countof(buf), NULL, NULL); WideCharToMultiByte(CP_ACP, 0, filename, -1, buf, _countof(buf), NULL, NULL);
return buf; return buf;
} }
static CStringW DoGetBaseName(LPCWSTR filename) static CStringW DoGetBaseName(PCWSTR filename)
{ {
WCHAR szBaseName[MAX_PATH]; WCHAR szBaseName[MAX_PATH];
StringCbCopyW(szBaseName, sizeof(szBaseName), filename); StringCbCopyW(szBaseName, sizeof(szBaseName), filename);
@ -69,7 +69,7 @@ DoGetNameInZip(const CStringW& basename, const CStringW& filename)
} }
static BOOL static BOOL
DoReadAllOfFile(LPCWSTR filename, CSimpleArray<BYTE>& contents, DoReadAllOfFile(PCWSTR filename, CSimpleArray<BYTE>& contents,
zip_fileinfo *pzi) zip_fileinfo *pzi)
{ {
contents.RemoveAll(); contents.RemoveAll();
@ -124,7 +124,7 @@ DoReadAllOfFile(LPCWSTR filename, CSimpleArray<BYTE>& contents,
} }
static void static void
DoAddFilesFromItem(CSimpleArray<CStringW>& files, LPCWSTR item) DoAddFilesFromItem(CSimpleArray<CStringW>& files, PCWSTR item)
{ {
if (!PathIsDirectoryW(item)) if (!PathIsDirectoryW(item))
{ {
@ -208,7 +208,7 @@ BOOL CZipCreator::runThread(CZipCreator *pCreator)
return FALSE; return FALSE;
} }
void CZipCreator::DoAddItem(LPCWSTR pszFile) void CZipCreator::DoAddItem(PCWSTR pszFile)
{ {
// canonicalize path // canonicalize path
WCHAR szPath[MAX_PATH]; WCHAR szPath[MAX_PATH];
@ -247,7 +247,7 @@ unsigned CZipCreatorImpl::JustDoIt()
CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE));
CStringW strText; CStringW strText;
strText.Format(IDS_NOFILES, static_cast<LPCWSTR>(m_items[0])); strText.Format(IDS_NOFILES, static_cast<PCWSTR>(m_items[0]));
MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
return CZCERR_NOFILES; return CZCERR_NOFILES;
@ -266,7 +266,7 @@ unsigned CZipCreatorImpl::JustDoIt()
CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE));
CStringW strText; CStringW strText;
strText.Format(IDS_CANTCREATEZIP, static_cast<LPCWSTR>(strZipName), err); strText.Format(IDS_CANTCREATEZIP, static_cast<PCWSTR>(strZipName), err);
MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
return err; return err;
@ -347,9 +347,9 @@ unsigned CZipCreatorImpl::JustDoIt()
CStringW strText; CStringW strText;
if (err < 0) if (err < 0)
strText.Format(IDS_CANTCREATEZIP, static_cast<LPCWSTR>(strZipName), err); strText.Format(IDS_CANTCREATEZIP, static_cast<PCWSTR>(strZipName), err);
else else
strText.Format(IDS_CANTREADFILE, static_cast<LPCWSTR>(strTarget)); strText.Format(IDS_CANTREADFILE, static_cast<PCWSTR>(strTarget));
MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
} }

View file

@ -22,7 +22,7 @@ public:
return new CZipCreator(); return new CZipCreator();
} }
virtual void DoAddItem(LPCWSTR pszFile); virtual void DoAddItem(PCWSTR pszFile);
static BOOL runThread(CZipCreator* pCreator); static BOOL runThread(CZipCreator* pCreator);
protected: protected:

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: CZipEnumerator * PURPOSE: CZipEnumerator
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
struct CZipEnumerator struct CZipEnumerator
@ -10,7 +11,7 @@ struct CZipEnumerator
private: private:
CComPtr<IZip> m_Zip; CComPtr<IZip> m_Zip;
bool m_First; bool m_First;
CAtlList<CStringA> m_Returned; CAtlList<CStringW> m_Returned;
public: public:
CZipEnumerator() CZipEnumerator()
:m_First(true) :m_First(true)
@ -33,15 +34,15 @@ public:
return true; return true;
} }
bool next_unique(const char* prefix, CStringA& name, bool& folder, unz_file_info64& info) bool next_unique(PCWSTR prefix, CStringW& name, bool& folder, unz_file_info64& info)
{ {
size_t len = strlen(prefix); size_t len = wcslen(prefix);
CStringA tmp; CStringW tmp;
while (next(tmp, info)) while (next(tmp, info))
{ {
if (!_strnicmp(tmp, prefix, len)) if (!_wcsnicmp(tmp, prefix, len))
{ {
int pos = tmp.Find('/', len); int pos = tmp.Find(L'/', len);
if (pos < 0) if (pos < 0)
{ {
name = tmp.Mid(len); name = tmp.Mid(len);
@ -66,7 +67,7 @@ public:
return false; return false;
} }
bool next(CStringA& name, unz_file_info64& info) bool next(CStringW& name, unz_file_info64& info)
{ {
int err; int err;
@ -84,10 +85,16 @@ public:
err = unzGetCurrentFileInfo64(uf, &info, NULL, 0, NULL, 0, NULL, 0); err = unzGetCurrentFileInfo64(uf, &info, NULL, 0, NULL, 0, NULL, 0);
if (err == UNZ_OK) if (err == UNZ_OK)
{ {
PSTR buf = name.GetBuffer(info.size_filename); CStringA nameA;
err = unzGetCurrentFileInfo64(uf, NULL, buf, name.GetAllocLength(), NULL, 0, NULL, 0); PSTR buf = nameA.GetBuffer(info.size_filename);
name.ReleaseBuffer(info.size_filename); err = unzGetCurrentFileInfo64(uf, NULL, buf, nameA.GetAllocLength(), NULL, 0, NULL, 0);
name.Replace('\\', '/'); nameA.ReleaseBuffer(info.size_filename);
nameA.Replace('\\', '/');
if (info.flag & MINIZIP_UTF8_FLAG)
Utf8ToWide(nameA, name);
else
name = CStringW(nameA);
} }
return err == UNZ_OK; return err == UNZ_OK;
} }

View file

@ -3,9 +3,11 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Zip extraction * PURPOSE: Zip extraction
* COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
#include <atlpath.h>
class CZipExtract : class CZipExtract :
public IZip public IZip
@ -204,7 +206,7 @@ public:
struct browse_info struct browse_info
{ {
HWND hWnd; HWND hWnd;
LPCWSTR Directory; PCWSTR Directory;
}; };
static INT CALLBACK s_BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lp, LPARAM pData) static INT CALLBACK s_BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lp, LPARAM pData)
@ -370,10 +372,10 @@ public:
eZipExtractError ExtractSingle( eZipExtractError ExtractSingle(
HWND hDlg, HWND hDlg,
LPCSTR FullPath, PCWSTR FullPath,
bool is_dir, bool is_dir,
unz_file_info64* Info, unz_file_info64* Info,
CStringA Name, CStringW Name,
CStringA Password, CStringA Password,
bool* bOverwriteAll, bool* bOverwriteAll,
const bool* bCancel, const bool* bCancel,
@ -383,7 +385,7 @@ public:
int err; int err;
BYTE Buffer[2048]; BYTE Buffer[2048];
DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE : SHPPFW_IGNOREFILENAME); DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE : SHPPFW_IGNOREFILENAME);
HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags); HRESULT hr = SHPathPrepareForWriteW(hDlg, NULL, FullPath, dwFlags);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
{ {
*ErrorCode = hr; *ErrorCode = hr;
@ -439,7 +441,7 @@ public:
return eOpenError; return eOpenError;
} }
HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hFile = CreateFileW(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
@ -467,7 +469,7 @@ public:
if (bOverwrite) if (bOverwrite)
{ {
hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); hFile = CreateFileW(FullPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
{ {
dwErr = GetLastError(); dwErr = GetLastError();
@ -482,7 +484,7 @@ public:
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
{ {
unzCloseCurrentFile(uf); unzCloseCurrentFile(uf);
DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr, *bOverwriteAll ? "Y" : "N"); DPRINT1("ERROR, CreateFile: 0x%x (%s)\n", dwErr, *bOverwriteAll ? "Y" : "N");
*ErrorCode = dwErr; *ErrorCode = dwErr;
return eFileError; return eFileError;
} }
@ -493,9 +495,9 @@ public:
if (*bCancel) if (*bCancel)
{ {
CloseHandle(hFile); CloseHandle(hFile);
BOOL deleteResult = DeleteFileA(FullPath); BOOL deleteResult = DeleteFileW(FullPath);
if (!deleteResult) if (!deleteResult)
DPRINT1("ERROR, DeleteFileA: 0x%x\n", GetLastError()); DPRINT1("ERROR, DeleteFile: 0x%x\n", GetLastError());
return eExtractAbort; return eExtractAbort;
} }
@ -575,8 +577,8 @@ public:
Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry); Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry);
Progress.SendMessage(PBM_SETPOS, 0, 0); Progress.SendMessage(PBM_SETPOS, 0, 0);
CStringA BaseDirectory = m_Directory; CStringW BaseDirectory = m_Directory;
CStringA Name; CStringW Name;
CStringA Password = m_Password; CStringA Password = m_Password;
unz_file_info64 Info; unz_file_info64 Info;
int CurrentFile = 0; int CurrentFile = 0;
@ -591,10 +593,15 @@ public:
bool is_dir = Name.GetLength() > 0 && Name[Name.GetLength()-1] == '/'; bool is_dir = Name.GetLength() > 0 && Name[Name.GetLength()-1] == '/';
char CombinedPath[MAX_PATH * 2] = { 0 }; // Build a combined path
PathCombineA(CombinedPath, BaseDirectory, Name); CPathW FullPath(BaseDirectory);
CStringA FullPath = CombinedPath; FullPath += Name;
FullPath.Replace('/', '\\'); /* SHPathPrepareForWriteA does not handle '/' */
// We use SHPathPrepareForWrite for this path.
// SHPathPrepareForWrite will prepare the necessary directories.
// Windows and ReactOS SHPathPrepareForWrite do not support '/'.
FullPath.m_strPath.Replace(L'/', L'\\');
Retry: Retry:
eZipExtractError Result = ExtractSingle(hDlg, FullPath, is_dir, &Info, Name, Password, &bOverwriteAll, bCancel, &err); eZipExtractError Result = ExtractSingle(hDlg, FullPath, is_dir, &Info, Name, Password, &bOverwriteAll, bCancel, &err);
if (Result != eDirectoryError) if (Result != eDirectoryError)
@ -613,13 +620,13 @@ public:
case eDirectoryError: case eDirectoryError:
{ {
char StrippedPath[MAX_PATH] = { 0 }; WCHAR StrippedPath[MAX_PATH] = { 0 };
StrCpyNA(StrippedPath, FullPath, _countof(StrippedPath)); StrCpyNW(StrippedPath, FullPath, _countof(StrippedPath));
if (!is_dir) if (!is_dir)
PathRemoveFileSpecA(StrippedPath); PathRemoveFileSpecW(StrippedPath);
PathStripPathA(StrippedPath); PathStripPathW(StrippedPath);
if (ShowExtractError(hDlg, (LPCSTR)&StrippedPath, err, eDirectoryError) == IDRETRY) if (ShowExtractError(hDlg, StrippedPath, err, eDirectoryError) == IDRETRY)
goto Retry; goto Retry;
Close(); Close();
return false; return false;
@ -665,11 +672,11 @@ public:
return true; return true;
} }
int ShowExtractError(HWND hDlg, LPCSTR path, int Error, eZipExtractError ErrorType) int ShowExtractError(HWND hDlg, PCWSTR path, int Error, eZipExtractError ErrorType)
{ {
CStringA strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE));
CStringA strErr, strText; CStringW strErr, strText;
PSTR Win32ErrorString; PWSTR Win32ErrorString;
if (ErrorType == eFileError || ErrorType == eOpenError) if (ErrorType == eFileError || ErrorType == eOpenError)
strText.LoadString(IDS_CANTEXTRACTFILE); strText.LoadString(IDS_CANTEXTRACTFILE);
@ -680,9 +687,9 @@ public:
if (ErrorType == eFileError || HRESULT_FACILITY(Error) == FACILITY_WIN32) if (ErrorType == eFileError || HRESULT_FACILITY(Error) == FACILITY_WIN32)
{ {
if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, ErrorType == eFileError ? Error : HRESULT_CODE(Error), 0, NULL, ErrorType == eFileError ? Error : HRESULT_CODE(Error), 0,
(PSTR)&Win32ErrorString, 0, NULL) != 0) (PWSTR)&Win32ErrorString, 0, NULL) != 0)
{ {
strErr.SetString(Win32ErrorString); strErr.SetString(Win32ErrorString);
LocalFree(Win32ErrorString); LocalFree(Win32ErrorString);
@ -693,7 +700,7 @@ public:
else if (strErr.GetLength() == 0) else if (strErr.GetLength() == 0)
strErr.Format(IDS_UNKNOWNERROR, Error); strErr.Format(IDS_UNKNOWNERROR, Error);
strText.Append("\r\n\r\n" + strErr); strText.Append(L"\r\n\r\n" + strErr);
UINT mbFlags = MB_ICONWARNING; UINT mbFlags = MB_ICONWARNING;
if (ErrorType == eDirectoryError) if (ErrorType == eDirectoryError)
@ -703,7 +710,7 @@ public:
else if (ErrorType == eOpenError) else if (ErrorType == eOpenError)
mbFlags |= MB_YESNO; mbFlags |= MB_YESNO;
return MessageBoxA(hDlg, strText, strTitle, mbFlags); return MessageBoxW(hDlg, strText, strTitle, mbFlags);
} }
}; };

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Main class * PURPOSE: Main class
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
struct FolderViewColumns struct FolderViewColumns
@ -37,7 +38,7 @@ class CZipFolder :
public IZip public IZip
{ {
CStringW m_ZipFile; CStringW m_ZipFile;
CStringA m_ZipDir; CStringW m_ZipDir;
CComHeapPtr<ITEMIDLIST> m_CurDir; CComHeapPtr<ITEMIDLIST> m_CurDir;
unzFile m_UnzipFile; unzFile m_UnzipFile;
@ -99,7 +100,7 @@ public:
return E_NOTIMPL; return E_NOTIMPL;
} }
// Adapted from CFileDefExt::GetFileTimeString // Adapted from CFileDefExt::GetFileTimeString
BOOL _GetFileTimeString(LPFILETIME lpFileTime, LPWSTR pwszResult, UINT cchResult) BOOL _GetFileTimeString(LPFILETIME lpFileTime, PWSTR pwszResult, UINT cchResult)
{ {
SYSTEMTIME st; SYSTEMTIME st;
@ -107,7 +108,7 @@ public:
return FALSE; return FALSE;
size_t cchRemaining = cchResult; size_t cchRemaining = cchResult;
LPWSTR pwszEnd = pwszResult; PWSTR pwszEnd = pwszResult;
int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pwszEnd, cchRemaining); int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pwszEnd, cchRemaining);
if (cchWritten) if (cchWritten)
--cchWritten; // GetDateFormatW returns count with terminating zero --cchWritten; // GetDateFormatW returns count with terminating zero
@ -158,9 +159,9 @@ public:
return GetDisplayNameOf(pidl, 0, &psd->str); return GetDisplayNameOf(pidl, 0, &psd->str);
case 1: /* Type */ case 1: /* Type */
{ {
SHFILEINFOA shfi; SHFILEINFOW shfi;
DWORD dwAttributes = isDir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; DWORD dwAttributes = isDir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
ULONG_PTR firet = SHGetFileInfoA(zipEntry->Name, dwAttributes, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME); ULONG_PTR firet = SHGetFileInfoW(zipEntry->Name, dwAttributes, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME);
if (!firet) if (!firet)
return E_FAIL; return E_FAIL;
return SHSetStrRet(&psd->str, shfi.szTypeName); return SHSetStrRet(&psd->str, shfi.szTypeName);
@ -226,7 +227,7 @@ public:
{ {
if (riid == IID_IShellFolder) if (riid == IID_IShellFolder)
{ {
CStringA newZipDir = m_ZipDir; CStringW newZipDir = m_ZipDir;
PCUIDLIST_RELATIVE curpidl = pidl; PCUIDLIST_RELATIVE curpidl = pidl;
while (curpidl->mkid.cb) while (curpidl->mkid.cb)
{ {
@ -236,7 +237,7 @@ public:
return E_FAIL; return E_FAIL;
} }
newZipDir += zipEntry->Name; newZipDir += zipEntry->Name;
newZipDir += '/'; newZipDir += L'/';
curpidl = ILGetNext(curpidl); curpidl = ILGetNext(curpidl);
} }
@ -262,7 +263,7 @@ public:
if (zipEntry1->ZipType != zipEntry2->ZipType) if (zipEntry1->ZipType != zipEntry2->ZipType)
result = zipEntry1->ZipType - zipEntry2->ZipType; result = zipEntry1->ZipType - zipEntry2->ZipType;
else else
result = stricmp(zipEntry1->Name, zipEntry2->Name); result = _wcsicmp(zipEntry1->Name, zipEntry2->Name);
if (!result && zipEntry1->ZipType == ZIP_PIDL_DIRECTORY) if (!result && zipEntry1->ZipType == ZIP_PIDL_DIRECTORY)
{ {
@ -392,14 +393,8 @@ public:
const ZipPidlEntry* zipEntry = _ZipFromIL(*apidl); const ZipPidlEntry* zipEntry = _ZipFromIL(*apidl);
if (zipEntry) if (zipEntry)
{ {
CComHeapPtr<WCHAR> pathW;
int len = MultiByteToWideChar(CP_ACP, 0, zipEntry->Name, -1, NULL, 0);
pathW.Allocate(len);
MultiByteToWideChar(CP_ACP, 0, zipEntry->Name, -1, pathW, len);
DWORD dwAttributes = (zipEntry->ZipType == ZIP_PIDL_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; DWORD dwAttributes = (zipEntry->ZipType == ZIP_PIDL_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
return SHCreateFileExtractIconW(pathW, dwAttributes, riid, ppvOut); return SHCreateFileExtractIconW(zipEntry->Name, dwAttributes, riid, ppvOut);
} }
} }
else if (riid == IID_IContextMenu && cidl >= 0) else if (riid == IID_IContextMenu && cidl >= 0)
@ -444,7 +439,7 @@ public:
if (!zipEntry) if (!zipEntry)
return E_FAIL; return E_FAIL;
return SHSetStrRet(strRet, (LPCSTR)zipEntry->Name); return SHSetStrRet(strRet, zipEntry->Name);
} }
STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
{ {
@ -479,7 +474,7 @@ public:
case GCS_VERBA: case GCS_VERBA:
return StringCchCopyA(pszName, cchMax, EXTRACT_VERBA); return StringCchCopyA(pszName, cchMax, EXTRACT_VERBA);
case GCS_VERBW: case GCS_VERBW:
return StringCchCopyW((LPWSTR)pszName, cchMax, EXTRACT_VERBW); return StringCchCopyW((PWSTR)pszName, cchMax, EXTRACT_VERBW);
case GCS_HELPTEXTA: case GCS_HELPTEXTA:
{ {
CStringA helpText(MAKEINTRESOURCEA(IDS_HELPTEXT)); CStringA helpText(MAKEINTRESOURCEA(IDS_HELPTEXT));
@ -488,7 +483,7 @@ public:
case GCS_HELPTEXTW: case GCS_HELPTEXTW:
{ {
CStringW helpText(MAKEINTRESOURCEA(IDS_HELPTEXT)); CStringW helpText(MAKEINTRESOURCEA(IDS_HELPTEXT));
return StringCchCopyW((LPWSTR)pszName, cchMax, helpText); return StringCchCopyW((PWSTR)pszName, cchMax, helpText);
} }
case GCS_VALIDATEA: case GCS_VALIDATEA:
case GCS_VALIDATEW: case GCS_VALIDATEW:
@ -621,7 +616,7 @@ public:
} }
STDMETHODIMP Initialize(PCWSTR zipFile, PCSTR zipDir, PCUIDLIST_ABSOLUTE curDir, PCUIDLIST_RELATIVE pidl) STDMETHODIMP Initialize(PCWSTR zipFile, PCWSTR zipDir, PCUIDLIST_ABSOLUTE curDir, PCUIDLIST_RELATIVE pidl)
{ {
m_ZipFile = zipFile; m_ZipFile = zipFile;
m_ZipDir = zipDir; m_ZipDir = zipDir;

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Ask the user for a password * PURPOSE: Ask the user for a password
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
@ -10,10 +11,10 @@
class CZipPassword : public CDialogImpl<CZipPassword> class CZipPassword : public CDialogImpl<CZipPassword>
{ {
private: private:
CStringA m_Filename; CStringW m_Filename;
CStringA* m_pPassword; CStringA* m_pPassword;
public: public:
CZipPassword(const char* filename, CStringA* Password) CZipPassword(PCWSTR filename, CStringA* Password)
:m_pPassword(Password) :m_pPassword(Password)
{ {
if (filename != NULL) if (filename != NULL)
@ -27,15 +28,15 @@ public:
/* No filename, so this is the question before starting to extract */ /* No filename, so this is the question before starting to extract */
if (m_Filename.IsEmpty()) if (m_Filename.IsEmpty())
{ {
CStringA message(MAKEINTRESOURCE(IDS_PASSWORD_ZIP_TEXT)); CStringW message(MAKEINTRESOURCEW(IDS_PASSWORD_ZIP_TEXT));
::SetDlgItemTextA(m_hWnd, IDC_MESSAGE, message); ::SetDlgItemTextW(m_hWnd, IDC_MESSAGE, message);
::ShowWindow(GetDlgItem(IDSKIP), SW_HIDE); ::ShowWindow(GetDlgItem(IDSKIP), SW_HIDE);
} }
else else
{ {
CStringA message; CStringW message;
message.FormatMessage(IDS_PASSWORD_FILE_TEXT, m_Filename.GetString()); message.FormatMessage(IDS_PASSWORD_FILE_TEXT, m_Filename.GetString());
::SetDlgItemTextA(m_hWnd, IDC_MESSAGE, message); ::SetDlgItemTextW(m_hWnd, IDC_MESSAGE, message);
} }
return TRUE; return TRUE;
} }
@ -64,10 +65,10 @@ public:
END_MSG_MAP() END_MSG_MAP()
}; };
eZipPasswordResponse _CZipAskPassword(HWND hDlg, const char* filename, CStringA& Password) eZipPasswordResponse _CZipAskPassword(HWND hDlg, PCWSTR filename, CStringA& Password)
{ {
if (filename) if (filename)
filename = PathFindFileNameA(filename); filename = PathFindFileNameW(filename);
CZipPassword password(filename, &Password); CZipPassword password(filename, &Password);
INT_PTR Result = password.DoModal(hDlg); INT_PTR Result = password.DoModal(hDlg);
switch (Result) switch (Result)

View file

@ -21,7 +21,7 @@
#include <reactos/debug.h> #include <reactos/debug.h>
#include <shellutils.h> #include <shellutils.h>
void Utf8ToWide(const CStringA& strUtf8, CStringW& strWide);
#define EXTRACT_VERBA "extract" #define EXTRACT_VERBA "extract"
#define EXTRACT_VERBW L"extract" #define EXTRACT_VERBW L"extract"
@ -41,6 +41,7 @@ WCHAR* guid2string(REFCLSID iid);
#define MINIZIP_PASSWORD_FLAG 1 #define MINIZIP_PASSWORD_FLAG 1
#define MINIZIP_UTF8_FLAG (1 << 11)
#include "minizip/unzip.h" #include "minizip/unzip.h"
#include "minizip/ioapi.h" #include "minizip/ioapi.h"
@ -52,7 +53,7 @@ extern zlib_filefunc64_def g_FFunc;
#include "zippidl.hpp" #include "zippidl.hpp"
#include "IZip.hpp" #include "IZip.hpp"
HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, const char* prefix, REFIID riid, LPVOID * ppvOut); HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, PCWSTR prefix, REFIID riid, LPVOID * ppvOut);
HRESULT _CExplorerCommandProvider_CreateInstance(IContextMenu* zipObject, REFIID riid, LPVOID * ppvOut); HRESULT _CExplorerCommandProvider_CreateInstance(IContextMenu* zipObject, REFIID riid, LPVOID * ppvOut);
HRESULT _CFolderViewCB_CreateInstance(REFIID riid, LPVOID * ppvOut); HRESULT _CFolderViewCB_CreateInstance(REFIID riid, LPVOID * ppvOut);
void _CZipExtract_runWizard(PCWSTR Filename); void _CZipExtract_runWizard(PCWSTR Filename);
@ -64,7 +65,7 @@ enum eZipPasswordResponse
eAccept, eAccept,
}; };
eZipPasswordResponse _CZipAskPassword(HWND hDlg, const char* filename, CStringA& Password); eZipPasswordResponse _CZipAskPassword(HWND hDlg, PCWSTR filename, CStringA& Password);
enum eZipConfirmResponse enum eZipConfirmResponse
{ {
@ -74,7 +75,7 @@ enum eZipConfirmResponse
eCancel eCancel
}; };
eZipConfirmResponse _CZipAskReplace(HWND hDlg, const char* FullPath); eZipConfirmResponse _CZipAskReplace(HWND hDlg, PCWSTR FullPath);
enum eZipExtractError enum eZipExtractError
{ {

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: zipfldr entrypoint * PURPOSE: zipfldr entrypoint
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
@ -47,8 +48,15 @@ static void init_zlib()
fill_win32_filefunc64W(&g_FFunc); 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 static BOOL
CreateEmptyFile(LPCWSTR pszFile) CreateEmptyFile(PCWSTR pszFile)
{ {
HANDLE hFile; HANDLE hFile;
hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
@ -62,7 +70,7 @@ CreateEmptyFile(LPCWSTR pszFile)
} }
static HRESULT static HRESULT
CreateSendToZip(LPCWSTR pszSendTo) CreateSendToZip(PCWSTR pszSendTo)
{ {
WCHAR szTarget[MAX_PATH], szSendToFile[MAX_PATH]; WCHAR szTarget[MAX_PATH], szSendToFile[MAX_PATH];
@ -80,7 +88,7 @@ CreateSendToZip(LPCWSTR pszSendTo)
} }
static HRESULT static HRESULT
GetDefaultUserSendTo(LPWSTR pszPath) GetDefaultUserSendTo(PWSTR pszPath)
{ {
return SHGetFolderPathW(NULL, CSIDL_SENDTO, INVALID_HANDLE_VALUE, return SHGetFolderPathW(NULL, CSIDL_SENDTO, INVALID_HANDLE_VALUE,
SHGFP_TYPE_DEFAULT, pszPath); SHGFP_TYPE_DEFAULT, pszPath);
@ -154,7 +162,7 @@ BOOL WINAPI
RouteTheCall( RouteTheCall(
IN HWND hWndOwner, IN HWND hWndOwner,
IN HINSTANCE hInstance, IN HINSTANCE hInstance,
IN LPCSTR lpStringArg, IN PCWSTR lpStringArg,
IN INT Show) IN INT Show)
{ {
CStringW path = lpStringArg; CStringW path = lpStringArg;

View file

@ -3,20 +3,24 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: zip pidl handling * PURPOSE: zip pidl handling
* COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include "precomp.h" #include "precomp.h"
LPITEMIDLIST _ILCreate(ZipPidlType Type, LPCSTR lpString, unz_file_info64& info) LPITEMIDLIST _ILCreate(ZipPidlType Type, PCWSTR lpString, unz_file_info64& info)
{ {
int cbData = sizeof(ZipPidlEntry) + strlen(lpString); size_t cbData = sizeof(ZipPidlEntry) + wcslen(lpString) * sizeof(WCHAR);
if (cbData > MAXWORD)
return NULL;
ZipPidlEntry* pidl = (ZipPidlEntry*)SHAlloc(cbData + sizeof(WORD)); ZipPidlEntry* pidl = (ZipPidlEntry*)SHAlloc(cbData + sizeof(WORD));
if (!pidl) if (!pidl)
return NULL; return NULL;
ZeroMemory(pidl, cbData + sizeof(WORD)); ZeroMemory(pidl, cbData + sizeof(WORD));
pidl->cb = cbData; pidl->cb = (WORD)cbData;
pidl->MagicType = 'z'; pidl->MagicType = 'z';
pidl->ZipType = Type; pidl->ZipType = Type;
@ -28,13 +32,12 @@ LPITEMIDLIST _ILCreate(ZipPidlType Type, LPCSTR lpString, unz_file_info64& info)
pidl->Password = info.flag & MINIZIP_PASSWORD_FLAG; pidl->Password = info.flag & MINIZIP_PASSWORD_FLAG;
} }
strcpy(pidl->Name, lpString); wcscpy(pidl->Name, lpString);
*(WORD*)((char*)pidl + cbData) = 0; *(WORD*)((char*)pidl + cbData) = 0; // The end of an ITEMIDLIST
return (LPITEMIDLIST)pidl; return (LPITEMIDLIST)pidl;
} }
const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl) const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl)
{ {
const ZipPidlEntry* zipPidl = (const ZipPidlEntry*)pidl; const ZipPidlEntry* zipPidl = (const ZipPidlEntry*)pidl;

View file

@ -3,6 +3,7 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: zip pidl handling * PURPOSE: zip pidl handling
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
@ -15,20 +16,19 @@ enum ZipPidlType
#include <pshpack1.h> #include <pshpack1.h>
struct ZipPidlEntry struct ZipPidlEntry
{ {
WORD cb; WORD cb; // This must be a WORD to keep compatibility to SHITEMID
BYTE MagicType; BYTE MagicType;
BOOLEAN Password;
ZipPidlType ZipType; ZipPidlType ZipType;
ULONG64 CompressedSize; ULONG64 CompressedSize;
ULONG64 UncompressedSize; ULONG64 UncompressedSize;
ULONG DosDate; ULONG DosDate;
BYTE Password;
char Name[1]; WCHAR Name[1];
}; };
#include <poppack.h> #include <poppack.h>
LPITEMIDLIST _ILCreate(ZipPidlType Type, LPCSTR lpString, unz_file_info64& info); LPITEMIDLIST _ILCreate(ZipPidlType Type, PCWSTR lpString, unz_file_info64& info);
const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl); const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl);