[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
This commit is contained in:
Katayama Hirofumi MZ 2019-12-01 21:20:53 +09:00 committed by GitHub
parent 62a95e4943
commit 962ff6e2fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 658 additions and 4 deletions

View file

@ -28,6 +28,8 @@ list(APPEND SOURCE
CExplorerCommand.cpp
CEnumZipContents.cpp
CFolderViewCB.cpp
CSendToZip.cpp
CZipCreater.cpp
CZipEnumerator.hpp
CZipExtract.cpp
CZipFolder.hpp

View file

@ -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<HDROP>(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;
}

View file

@ -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<CSendToZip, &CLSID_ZipFolderSendTo>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IDropTarget,
public IPersistFile
{
CComPtr<IDataObject> 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

View file

@ -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 <process.h>
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<BYTE>& 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<LPBYTE>(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<CStringW>& 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<CStringW> 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<CZipCreator *>(arg);
return pCreater->m_pimpl->JustDoIt();
}
BOOL CZipCreator::runThread(CZipCreator *pCreater)
{
unsigned tid = 0;
HANDLE hThread = reinterpret_cast<HANDLE>(
_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<CStringW> 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<LPCWSTR>(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<LPCWSTR>(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<BYTE> 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<LPCWSTR>(strZipName), err);
else
strText.Format(IDS_CANTREADFILE, static_cast<LPCWSTR>(strTarget));
MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
}
return err;
}

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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 "एक गंतव्य चुनें"

View file

@ -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"

View file

@ -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 "展開先を選んで下さい"

View file

@ -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"

View file

@ -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"

View file

@ -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 "Укажите путь"

View file

@ -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"

View file

@ -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 "选择一个目标文件夹"

View file

@ -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 */

View file

@ -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}'
}
}
}

View file

@ -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

View file

@ -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;