From: Katayama Hirofumi MZ Date: Sun, 1 Dec 2019 12:20:53 +0000 (+0900) Subject: [SHELLEXT][ZIPFLDR] Implement ZIP creation (#2114) X-Git-Tag: 0.4.14-RC~1043 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=962ff6e2fa96dd9f6f5fee0e04551d4a54c076ec;hp=62a95e4943285e81d0c678975e7378bd1490d74d [SHELLEXT][ZIPFLDR] Implement ZIP creation (#2114) This PR will implement *.ZFSendToTarget file type that will realize SendTo ZIP folder in future. CORE-16495, CORE-12562 --- diff --git a/dll/shellext/zipfldr/CMakeLists.txt b/dll/shellext/zipfldr/CMakeLists.txt index 3c39dc45c3e..a0244d642aa 100644 --- a/dll/shellext/zipfldr/CMakeLists.txt +++ b/dll/shellext/zipfldr/CMakeLists.txt @@ -28,6 +28,8 @@ list(APPEND SOURCE CExplorerCommand.cpp CEnumZipContents.cpp CFolderViewCB.cpp + CSendToZip.cpp + CZipCreater.cpp CZipEnumerator.hpp CZipExtract.cpp CZipFolder.hpp diff --git a/dll/shellext/zipfldr/CSendToZip.cpp b/dll/shellext/zipfldr/CSendToZip.cpp new file mode 100644 index 00000000000..9ec9bd5dc7a --- /dev/null +++ b/dll/shellext/zipfldr/CSendToZip.cpp @@ -0,0 +1,90 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: SendTo handler + * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) + * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "precomp.h" + +STDMETHODIMP +CSendToZip::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, + DWORD *pdwEffect) +{ + m_pDataObject = pDataObj; + + FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + m_fCanDragDrop = SUCCEEDED(pDataObj->QueryGetData(&etc)); + + if (m_fCanDragDrop) + *pdwEffect &= DROPEFFECT_COPY; + else + *pdwEffect = DROPEFFECT_NONE; + + return S_OK; +} + +STDMETHODIMP CSendToZip::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) +{ + if (m_fCanDragDrop) + *pdwEffect &= DROPEFFECT_COPY; + else + *pdwEffect = DROPEFFECT_NONE; + + return S_OK; +} + +STDMETHODIMP CSendToZip::DragLeave() +{ + m_fCanDragDrop = FALSE; + m_pDataObject.Release(); + return S_OK; +} + +STDMETHODIMP +CSendToZip::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, + DWORD *pdwEffect) +{ + m_pDataObject = pDataObj; + *pdwEffect &= DROPEFFECT_COPY; + + if (!pDataObj || !m_fCanDragDrop || !*pdwEffect) + { + DPRINT1("Drop failed: %d %d %d\n", + !pDataObj, !m_fCanDragDrop, !*pdwEffect); + *pdwEffect = 0; + DragLeave(); + return E_FAIL; + } + + STGMEDIUM stg; + FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + HRESULT hr = pDataObj->GetData(&etc, &stg); + if (FAILED_UNEXPECTEDLY(hr)) + { + *pdwEffect = 0; + DragLeave(); + return E_FAIL; + } + + HDROP hDrop = reinterpret_cast(stg.hGlobal); + UINT cItems = ::DragQueryFileW(hDrop, -1, NULL, 0); + + CZipCreator *pCreater = CZipCreator::DoCreate(); + + for (UINT iItem = 0; iItem < cItems; ++iItem) + { + WCHAR szPath[MAX_PATH]; + DragQueryFileW(hDrop, iItem, szPath, _countof(szPath)); + + pCreater->DoAddItem(szPath); + } + + ::ReleaseStgMedium(&stg); + + CZipCreator::runThread(pCreater); // pCreater is deleted in runThread + + DragLeave(); + return hr; +} diff --git a/dll/shellext/zipfldr/CSendToZip.hpp b/dll/shellext/zipfldr/CSendToZip.hpp new file mode 100644 index 00000000000..1f3eb248a13 --- /dev/null +++ b/dll/shellext/zipfldr/CSendToZip.hpp @@ -0,0 +1,79 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: SendTo handler + * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) + * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#ifndef CSENDTOZIP_HPP_ +#define CSENDTOZIP_HPP_ + +class CSendToZip : + public CComCoClass, + public CComObjectRootEx, + public IDropTarget, + public IPersistFile +{ + CComPtr m_pDataObject; + BOOL m_fCanDragDrop; + +public: + CSendToZip() : m_fCanDragDrop(FALSE) + { + InterlockedIncrement(&g_ModuleRefCnt); + } + + virtual ~CSendToZip() + { + InterlockedDecrement(&g_ModuleRefCnt); + } + + // *** IShellFolder2 methods *** + STDMETHODIMP DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + STDMETHODIMP DragLeave(); + STDMETHODIMP Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + + // *** IPersistFile methods *** + STDMETHODIMP IsDirty() + { + return S_FALSE; + } + STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode) + { + return S_OK; + } + STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember) + { + return E_FAIL; + } + STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName) + { + return E_FAIL; + } + STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName) + { + return E_FAIL; + } + + // *** IPersist methods *** + STDMETHODIMP GetClassID(CLSID *pclsid) + { + return E_FAIL; + } + +public: + DECLARE_NO_REGISTRY() // Handled manually + DECLARE_NOT_AGGREGATABLE(CSendToZip) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CSendToZip) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) + COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + END_COM_MAP() +}; + +#endif diff --git a/dll/shellext/zipfldr/CZipCreater.cpp b/dll/shellext/zipfldr/CZipCreater.cpp new file mode 100644 index 00000000000..694128b6bcb --- /dev/null +++ b/dll/shellext/zipfldr/CZipCreater.cpp @@ -0,0 +1,358 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * 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) + */ + +#include "precomp.h" +#include "atlsimpcoll.h" +#include "minizip/zip.h" +#include "minizip/iowin32.h" +#include + +static CStringW DoGetZipName(LPCWSTR filename) +{ + WCHAR szPath[MAX_PATH]; + StringCbCopyW(szPath, sizeof(szPath), filename); + PathRemoveExtensionW(szPath); + + CStringW ret = szPath; + ret += L".zip"; + + UINT i = 2; + while (PathFileExistsW(ret)) + { + CStringW str; + str.Format(L" (%u).zip", i++); + + ret = szPath; + ret += str; + } + + return ret; +} + +static CStringA DoGetAnsiName(LPCWSTR filename) +{ + CHAR buf[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, filename, -1, buf, _countof(buf), NULL, NULL); + return buf; +} + +static CStringW DoGetBaseName(LPCWSTR filename) +{ + WCHAR szBaseName[MAX_PATH]; + StringCbCopyW(szBaseName, sizeof(szBaseName), filename); + PathRemoveFileSpecW(szBaseName); + PathAddBackslashW(szBaseName); + return szBaseName; +} + +static CStringA +DoGetNameInZip(const CStringW& basename, const CStringW& filename) +{ + CStringW basenameI = basename, filenameI = filename; + basenameI.MakeUpper(); + filenameI.MakeUpper(); + + CStringW ret; + if (filenameI.Find(basenameI) == 0) + ret = filename.Mid(basename.GetLength()); + else + ret = filename; + + ret.Replace(L'\\', L'/'); + + return DoGetAnsiName(ret); +} + +static BOOL +DoReadAllOfFile(LPCWSTR filename, CSimpleArray& contents, + zip_fileinfo *pzi) +{ + contents.RemoveAll(); + + HANDLE hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + DPRINT1("%S: cannot open\n", filename); + return FALSE; + } + + FILETIME ft, ftLocal; + ZeroMemory(pzi, sizeof(*pzi)); + if (GetFileTime(hFile, NULL, NULL, &ft)) + { + SYSTEMTIME st; + FileTimeToLocalFileTime(&ft, &ftLocal); + FileTimeToSystemTime(&ftLocal, &st); + pzi->tmz_date.tm_sec = st.wSecond; + pzi->tmz_date.tm_min = st.wMinute; + pzi->tmz_date.tm_hour = st.wHour; + pzi->tmz_date.tm_mday = st.wDay; + pzi->tmz_date.tm_mon = st.wMonth - 1; + pzi->tmz_date.tm_year = st.wYear; + } + + const DWORD cbBuff = 0x7FFF; + LPBYTE pbBuff = reinterpret_cast(CoTaskMemAlloc(cbBuff)); + if (!pbBuff) + { + DPRINT1("Out of memory\n"); + CloseHandle(hFile); + return FALSE; + } + + for (;;) + { + DWORD cbRead; + if (!ReadFile(hFile, pbBuff, cbBuff, &cbRead, NULL) || !cbRead) + break; + + for (DWORD i = 0; i < cbRead; ++i) + contents.Add(pbBuff[i]); + } + + CoTaskMemFree(pbBuff); + CloseHandle(hFile); + + return TRUE; +} + +static void +DoAddFilesFromItem(CSimpleArray& files, LPCWSTR item) +{ + if (!PathIsDirectoryW(item)) + { + files.Add(item); + return; + } + + WCHAR szPath[MAX_PATH]; + StringCbCopyW(szPath, sizeof(szPath), item); + PathAppendW(szPath, L"*"); + + WIN32_FIND_DATAW find; + HANDLE hFind = FindFirstFileW(szPath, &find); + if (hFind == INVALID_HANDLE_VALUE) + return; + + do + { + if (wcscmp(find.cFileName, L".") == 0 || + wcscmp(find.cFileName, L"..") == 0) + { + continue; + } + + StringCbCopyW(szPath, sizeof(szPath), item); + PathAppendW(szPath, find.cFileName); + + if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + DoAddFilesFromItem(files, szPath); + else + files.Add(szPath); + } while (FindNextFileW(hFind, &find)); + + FindClose(hFind); +} + +struct CZipCreatorImpl +{ + CSimpleArray m_items; + + unsigned JustDoIt(); +}; + +CZipCreator::CZipCreator() : m_pimpl(new CZipCreatorImpl) +{ + InterlockedIncrement(&g_ModuleRefCnt); +} + +CZipCreator::~CZipCreator() +{ + InterlockedDecrement(&g_ModuleRefCnt); + delete m_pimpl; +} + +static unsigned __stdcall +create_zip_function(void *arg) +{ + CZipCreator *pCreater = reinterpret_cast(arg); + return pCreater->m_pimpl->JustDoIt(); +} + +BOOL CZipCreator::runThread(CZipCreator *pCreater) +{ + unsigned tid = 0; + HANDLE hThread = reinterpret_cast( + _beginthreadex(NULL, 0, create_zip_function, pCreater, 0, &tid)); + + if (hThread) + { + CloseHandle(hThread); + return TRUE; + } + + DPRINT1("hThread == NULL\n"); + + CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); + CStringW strText(MAKEINTRESOURCEW(IDS_CANTSTARTTHREAD)); + MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); + + delete pCreater; + return FALSE; +} + +void CZipCreator::DoAddItem(LPCWSTR pszFile) +{ + // canonicalize path + WCHAR szPath[MAX_PATH]; + GetFullPathNameW(pszFile, _countof(szPath), szPath, NULL); + + m_pimpl->m_items.Add(szPath); +} + +enum CZC_ERROR +{ + CZCERR_ZEROITEMS = 1, + CZCERR_NOFILES, + CZCERR_CREATE, + CZCERR_READ +}; + +unsigned CZipCreatorImpl::JustDoIt() +{ + // TODO: Show progress. + + if (m_items.GetSize() <= 0) + { + DPRINT1("GetSize() <= 0\n"); + return CZCERR_ZEROITEMS; + } + + CSimpleArray files; + for (INT iItem = 0; iItem < m_items.GetSize(); ++iItem) + { + DoAddFilesFromItem(files, m_items[iItem]); + } + + if (files.GetSize() <= 0) + { + DPRINT1("files.GetSize() <= 0\n"); + + CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); + CStringW strText; + strText.Format(IDS_NOFILES, static_cast(m_items[0])); + MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); + + return CZCERR_NOFILES; + } + + zlib_filefunc64_def ffunc; + fill_win32_filefunc64W(&ffunc); + + CStringW strZipName = DoGetZipName(m_items[0]); + zipFile zf = zipOpen2_64(strZipName, APPEND_STATUS_CREATE, NULL, &ffunc); + if (zf == 0) + { + DPRINT1("zf == 0\n"); + + int err = CZCERR_CREATE; + + CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); + CStringW strText; + strText.Format(IDS_CANTCREATEZIP, static_cast(strZipName), err); + MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); + + return err; + } + + // TODO: password + const char *password = NULL; + int zip64 = 1; // always zip64 + zip_fileinfo zi; + + int err = 0; + CStringW strTarget, strBaseName = DoGetBaseName(m_items[0]); + for (INT iFile = 0; iFile < files.GetSize(); ++iFile) + { + const CStringW& strFile = files[iFile]; + + CSimpleArray contents; + if (!DoReadAllOfFile(strFile, contents, &zi)) + { + DPRINT1("DoReadAllOfFile failed\n"); + err = CZCERR_READ; + strTarget = strFile; + break; + } + + unsigned long crc = 0; + if (password) + { + // TODO: crc = ...; + } + + CStringA strNameInZip = DoGetNameInZip(strBaseName, strFile); + err = zipOpenNewFileInZip3_64(zf, + strNameInZip, + &zi, + NULL, + 0, + NULL, + 0, + NULL, + Z_DEFLATED, + Z_DEFAULT_COMPRESSION, + 0, + -MAX_WBITS, + DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, + password, + crc, + zip64); + if (err) + { + DPRINT1("zipOpenNewFileInZip3_64\n"); + break; + } + + err = zipWriteInFileInZip(zf, contents.GetData(), contents.GetSize()); + if (err) + { + DPRINT1("zipWriteInFileInZip\n"); + break; + } + + err = zipCloseFileInZip(zf); + if (err) + { + DPRINT1("zipCloseFileInZip\n"); + break; + } + } + + zipClose(zf, NULL); + + if (err) + { + DeleteFileW(strZipName); + + CStringW strTitle(MAKEINTRESOURCEW(IDS_ERRORTITLE)); + + CStringW strText; + if (err < 0) + strText.Format(IDS_CANTCREATEZIP, static_cast(strZipName), err); + else + strText.Format(IDS_CANTREADFILE, static_cast(strTarget)); + + MessageBoxW(NULL, strText, strTitle, MB_ICONERROR); + } + + return err; +} diff --git a/dll/shellext/zipfldr/CZipCreater.hpp b/dll/shellext/zipfldr/CZipCreater.hpp new file mode 100644 index 00000000000..52fb14f9ead --- /dev/null +++ b/dll/shellext/zipfldr/CZipCreater.hpp @@ -0,0 +1,32 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * 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) + */ +#ifndef CZIPCREATER_HPP_ +#define CZIPCREATER_HPP_ + +struct CZipCreatorImpl; + +class CZipCreator +{ +public: + struct CZipCreatorImpl *m_pimpl; + + virtual ~CZipCreator(); + + static CZipCreator* DoCreate() + { + return new CZipCreator(); + } + + virtual void DoAddItem(LPCWSTR pszFile); + static BOOL runThread(CZipCreator* pCreater); + +protected: + CZipCreator(); +}; + +#endif diff --git a/dll/shellext/zipfldr/lang/de-DE.rc b/dll/shellext/zipfldr/lang/de-DE.rc index 5925822e051..6f50cb7d0d0 100644 --- a/dll/shellext/zipfldr/lang/de-DE.rc +++ b/dll/shellext/zipfldr/lang/de-DE.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Änderungsdatum" IDS_YES "Ja" IDS_NO "Nein" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Extrahier-Assistent" IDS_WIZ_DEST_TITLE "Ziel auswählen" diff --git a/dll/shellext/zipfldr/lang/en-US.rc b/dll/shellext/zipfldr/lang/en-US.rc index bba5be5c870..a73ad541688 100644 --- a/dll/shellext/zipfldr/lang/en-US.rc +++ b/dll/shellext/zipfldr/lang/en-US.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Date modified" IDS_YES "Yes" IDS_NO "No" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Extraction Wizard" IDS_WIZ_DEST_TITLE "Select a Destination" diff --git a/dll/shellext/zipfldr/lang/et-EE.rc b/dll/shellext/zipfldr/lang/et-EE.rc index c9a7cc0f982..eb2b0280afb 100644 --- a/dll/shellext/zipfldr/lang/et-EE.rc +++ b/dll/shellext/zipfldr/lang/et-EE.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Kuupäeval muudetud" IDS_YES "Jah" IDS_NO "Ei" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Ekstraktimise visard" IDS_WIZ_DEST_TITLE "Vali sihtkoht" diff --git a/dll/shellext/zipfldr/lang/fr-FR.rc b/dll/shellext/zipfldr/lang/fr-FR.rc index 19d4520a605..24decc1fa3c 100644 --- a/dll/shellext/zipfldr/lang/fr-FR.rc +++ b/dll/shellext/zipfldr/lang/fr-FR.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Date de modification" IDS_YES "Oui" IDS_NO "Non" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Assistant d'extraction" IDS_WIZ_DEST_TITLE "Choisir une destination" diff --git a/dll/shellext/zipfldr/lang/hi-IN.rc b/dll/shellext/zipfldr/lang/hi-IN.rc index 7794f630cb3..cf31cce8e32 100644 --- a/dll/shellext/zipfldr/lang/hi-IN.rc +++ b/dll/shellext/zipfldr/lang/hi-IN.rc @@ -55,6 +55,11 @@ BEGIN IDS_COL_DATE_MOD "तिथि संशोधित" IDS_YES "हाँ" IDS_NO "नहीं" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "निष्कर्षण विज़ार्ड" IDS_WIZ_DEST_TITLE "एक गंतव्य चुनें" diff --git a/dll/shellext/zipfldr/lang/it-IT.rc b/dll/shellext/zipfldr/lang/it-IT.rc index 9f8864383f7..d3572fa0101 100644 --- a/dll/shellext/zipfldr/lang/it-IT.rc +++ b/dll/shellext/zipfldr/lang/it-IT.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Data modificata" IDS_YES "Sì" IDS_NO "No" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Estrazione Guidata" IDS_WIZ_DEST_TITLE "Seleziona una Destinazione" diff --git a/dll/shellext/zipfldr/lang/ja-JP.rc b/dll/shellext/zipfldr/lang/ja-JP.rc index 63564b7200d..157e6717dac 100644 --- a/dll/shellext/zipfldr/lang/ja-JP.rc +++ b/dll/shellext/zipfldr/lang/ja-JP.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "変更日" IDS_YES "はい" IDS_NO "いいえ" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "展開ウィザード" IDS_WIZ_DEST_TITLE "展開先を選んで下さい" diff --git a/dll/shellext/zipfldr/lang/pl-PL.rc b/dll/shellext/zipfldr/lang/pl-PL.rc index c4130cb6db2..fcdb0436d22 100644 --- a/dll/shellext/zipfldr/lang/pl-PL.rc +++ b/dll/shellext/zipfldr/lang/pl-PL.rc @@ -67,6 +67,11 @@ BEGIN IDS_COL_DATE_MOD "Data modyfikacji" IDS_YES "Tak" IDS_NO "Nie" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Kreator wyodrębniania" IDS_WIZ_DEST_TITLE "Wybierz miejsce docelowe" diff --git a/dll/shellext/zipfldr/lang/ro-RO.rc b/dll/shellext/zipfldr/lang/ro-RO.rc index 31642b0f48a..cb15956e6cb 100644 --- a/dll/shellext/zipfldr/lang/ro-RO.rc +++ b/dll/shellext/zipfldr/lang/ro-RO.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Data modificată" IDS_YES "Da" IDS_NO "Nu" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Asistent de extracție" IDS_WIZ_DEST_TITLE "Selectați o Destinație" diff --git a/dll/shellext/zipfldr/lang/ru-RU.rc b/dll/shellext/zipfldr/lang/ru-RU.rc index 89096a34401..1791169c937 100644 --- a/dll/shellext/zipfldr/lang/ru-RU.rc +++ b/dll/shellext/zipfldr/lang/ru-RU.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Дата изменения" IDS_YES "Да" IDS_NO "Нет" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Мастер извлечения архивов" IDS_WIZ_DEST_TITLE "Укажите путь" diff --git a/dll/shellext/zipfldr/lang/sv-SE.rc b/dll/shellext/zipfldr/lang/sv-SE.rc index a2f1c90c73c..886dddfe8bf 100644 --- a/dll/shellext/zipfldr/lang/sv-SE.rc +++ b/dll/shellext/zipfldr/lang/sv-SE.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "Ändrad den" IDS_YES "Ja" IDS_NO "Nej" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "Extraheringsguiden" IDS_WIZ_DEST_TITLE "Välj ett mål" diff --git a/dll/shellext/zipfldr/lang/zh-CN.rc b/dll/shellext/zipfldr/lang/zh-CN.rc index 27066adfdf9..6d69c012991 100644 --- a/dll/shellext/zipfldr/lang/zh-CN.rc +++ b/dll/shellext/zipfldr/lang/zh-CN.rc @@ -68,6 +68,11 @@ BEGIN IDS_COL_DATE_MOD "修改日期" IDS_YES "是" IDS_NO "否" + IDS_ERRORTITLE "Compressed (zipped) Folders Error" + IDS_CANTSTARTTHREAD "Cannot start thread to compress files." + IDS_NOFILES "The specified directory '%s' is empty, so Compressed (zipped) Folders cannot add it to the archive." + IDS_CANTCREATEZIP "Failed to create a compressed folder '%s' (Error Code: %d)." + IDS_CANTREADFILE "Cannot read file '%s'." IDS_WIZ_TITLE "解压向导" IDS_WIZ_DEST_TITLE "选择一个目标文件夹" diff --git a/dll/shellext/zipfldr/precomp.h b/dll/shellext/zipfldr/precomp.h index e25e2f19024..ed61dc75dcc 100644 --- a/dll/shellext/zipfldr/precomp.h +++ b/dll/shellext/zipfldr/precomp.h @@ -78,5 +78,7 @@ eZipConfirmResponse _CZipAskReplace(HWND hDlg, const char* FullPath); #include "CZipEnumerator.hpp" #include "CZipFolder.hpp" +#include "CZipCreater.hpp" +#include "CSendToZip.hpp" #endif /* ZIPFLDR_PRECOMP_H */ diff --git a/dll/shellext/zipfldr/res/zipfldr.rgs b/dll/shellext/zipfldr/res/zipfldr.rgs index 82cfc8dfaeb..c57aeae4815 100644 --- a/dll/shellext/zipfldr/res/zipfldr.rgs +++ b/dll/shellext/zipfldr/res/zipfldr.rgs @@ -12,10 +12,26 @@ HKCR val UseDropHandler = s '' } } - '{b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af}' = s 'Compressed (zipped) Folder Menu' + '{B8CDCB65-B1BF-4B42-9428-1DFDB7EE92AF}' = s 'Compressed (zipped) Folder Menu' { InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' } } + '{888DCA60-FC0A-11CF-8F0F-00C04FD7D062}' = s 'Compressed (zipped) Folder SendTo Target' + { + val EditFlags = d '0x01' + val FriendlyTypeName = s '%MODULE%,-10226' + val NeverShowExt = s '' + val NoOpen = s 'Drag Files onto this icon to compress them.' + DefaultIcon = s '%MODULE%' { } + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + ShellEx + { + DropHandler = s '{888DCA60-FC0A-11CF-8F0F-00C04FD7D062}' { } + } + } } NoRemove Applications { @@ -24,7 +40,7 @@ HKCR NoRemove CompressedFolder { FriendlyTypeName = s '%MODULE%,-10195' - CLSID = s '{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}' + CLSID = s '{E88DCCE0-B7B3-11D1-A9F0-00AA0060FA31}' DefaultIcon = s '%MODULE%' NoRemove Shell @@ -41,7 +57,7 @@ HKCR { NoRemove ContextMenuHandlers { - ForceRemove '{b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af}' = s 'Compressed (zipped) Folder Menu' + ForceRemove '{B8CDCB65-B1BF-4B42-9428-1DFDB7EE92AF}' = s 'Compressed (zipped) Folder Menu' { } } @@ -52,3 +68,13 @@ HKCR val 'Content Type' = s 'application/x-zip-compressed' } } +HKLM +{ + NoRemove Software + { + NoRemove Classes + { + '.ZFSendToTarget' = s 'CLSID\{888DCA60-FC0A-11CF-8F0F-00C04FD7D062}' + } + } +} diff --git a/dll/shellext/zipfldr/resource.h b/dll/shellext/zipfldr/resource.h index b14faeb7d28..b294e823b77 100644 --- a/dll/shellext/zipfldr/resource.h +++ b/dll/shellext/zipfldr/resource.h @@ -35,7 +35,11 @@ #define IDS_COL_DATE_MOD 106 #define IDS_YES 107 #define IDS_NO 108 - +#define IDS_ERRORTITLE 109 +#define IDS_CANTSTARTTHREAD 110 +#define IDS_NOFILES 111 +#define IDS_CANTCREATEZIP 112 +#define IDS_CANTREADFILE 113 /* Wizard titles */ #define IDS_WIZ_TITLE 8000 diff --git a/dll/shellext/zipfldr/zipfldr.cpp b/dll/shellext/zipfldr/zipfldr.cpp index 2b9e5b63801..eecb1ac02de 100644 --- a/dll/shellext/zipfldr/zipfldr.cpp +++ b/dll/shellext/zipfldr/zipfldr.cpp @@ -31,6 +31,7 @@ public: BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_ZipFolderStorageHandler, CZipFolder) OBJECT_ENTRY(CLSID_ZipFolderContextMenu, CZipFolder) + OBJECT_ENTRY(CLSID_ZipFolderSendTo, CSendToZip) END_OBJECT_MAP() CZipFldrModule gModule;