ReactOS 0.4.16-dev-2284-g3529151
CZipCreator.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Zip Shell Extension
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Create a zip file
5 * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6 * Copyright 2019-2026 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9#include "precomp.h"
10#include "atlsimpcoll.h"
11#include "minizip/zip.h"
12#include "minizip/iowin32.h"
13#include <process.h>
14
16{
17 return crc32(0L, reinterpret_cast<const BYTE*>(name), strlen(name));
18}
19
21{
25
27 ret += L".zip";
28
29 UINT i = 2;
30 while (PathFileExistsW(ret))
31 {
33 str.Format(L" (%u).zip", i++);
34
35 ret = szPath;
36 ret += str;
37 }
38
39 return ret;
40}
41
43{
44 WCHAR szBaseName[MAX_PATH];
45 StringCbCopyW(szBaseName, sizeof(szBaseName), filename);
46 PathRemoveFileSpecW(szBaseName);
47 PathAddBackslashW(szBaseName);
48 return szBaseName;
49}
50
51static CStringA
53{
54 CStringW basenameI = basename, filenameI = filename;
55 basenameI.MakeUpper();
56 filenameI.MakeUpper();
57
59 if (filenameI.Find(basenameI) == 0)
60 ret = filename.Mid(basename.GetLength());
61 else
62 ret = filename;
63
64 ret.Replace(L'\\', L'/');
65
66 return CStringA(CW2AEX<MAX_PATH>(ret, nCodePage));
67}
68
69static BOOL
71 zip_fileinfo *pzi)
72{
73 contents.RemoveAll();
74
79 {
80 DPRINT1("%S: cannot open\n", filename);
81 return FALSE;
82 }
83
84 FILETIME ft, ftLocal;
85 ZeroMemory(pzi, sizeof(*pzi));
86 if (GetFileTime(hFile, NULL, NULL, &ft))
87 {
88 SYSTEMTIME st;
89 FileTimeToLocalFileTime(&ft, &ftLocal);
90 FileTimeToSystemTime(&ftLocal, &st);
91 pzi->tmz_date.tm_sec = st.wSecond;
92 pzi->tmz_date.tm_min = st.wMinute;
93 pzi->tmz_date.tm_hour = st.wHour;
94 pzi->tmz_date.tm_mday = st.wDay;
95 pzi->tmz_date.tm_mon = st.wMonth - 1;
96 pzi->tmz_date.tm_year = st.wYear;
97 }
98
99 const DWORD cbBuff = 0x7FFF;
100 LPBYTE pbBuff = reinterpret_cast<LPBYTE>(CoTaskMemAlloc(cbBuff));
101 if (!pbBuff)
102 {
103 DPRINT1("Out of memory\n");
105 return FALSE;
106 }
107
108 for (;;)
109 {
110 DWORD cbRead;
111 if (!ReadFile(hFile, pbBuff, cbBuff, &cbRead, NULL) || !cbRead)
112 break;
113
114 for (DWORD i = 0; i < cbRead; ++i)
115 contents.Add(pbBuff[i]);
116 }
117
118 CoTaskMemFree(pbBuff);
120
121 return TRUE;
122}
123
124static void
126{
128 {
129 files.Add(item);
130 return;
131 }
132
134 StringCbCopyW(szPath, sizeof(szPath), item);
135 PathAppendW(szPath, L"*");
136
138 HANDLE hFind = FindFirstFileW(szPath, &find);
139 if (hFind == INVALID_HANDLE_VALUE)
140 return;
141
142 do
143 {
144 if (wcscmp(find.cFileName, L".") == 0 ||
145 wcscmp(find.cFileName, L"..") == 0)
146 {
147 continue;
148 }
149
150 StringCbCopyW(szPath, sizeof(szPath), item);
151 PathAppendW(szPath, find.cFileName);
152
153 if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
155 else
156 files.Add(szPath);
157 } while (FindNextFileW(hFind, &find));
158
159 FindClose(hFind);
160}
161
163{
167
168 unsigned JustDoIt();
169};
170
171CZipCreator* CZipCreator::DoCreate(PCWSTR pszExistingZip, PCWSTR pszTargetDir)
172{
173 CZipCreator* pCreator = new CZipCreator();
174 if (pszExistingZip)
175 pCreator->m_pimpl->m_ExistingZip = pszExistingZip;
176 if (pszTargetDir)
177 pCreator->m_pimpl->m_TargetDir = pszTargetDir;
178 return pCreator;
179}
180
182{
184}
185
187{
189 delete m_pimpl;
190}
191
192static unsigned __stdcall
194{
195 CZipCreator *pCreator = reinterpret_cast<CZipCreator *>(arg);
196 unsigned result = pCreator->m_pimpl->JustDoIt();
197
198 if (result == 0 && pCreator->m_pidlNotify)
200
201 return result;
202}
203
205{
206 unsigned tid = 0;
207 HANDLE hThread = reinterpret_cast<HANDLE>(
208 _beginthreadex(NULL, 0, create_zip_function, pCreator, 0, &tid));
209
210 if (hThread)
211 {
213 return TRUE;
214 }
215
216 DPRINT1("hThread == NULL\n");
217
220 MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
221
222 delete pCreator;
223 return FALSE;
224}
225
227{
228 // canonicalize path
231
232 m_pimpl->m_items.Add(szPath);
233}
234
236{
242
244{
245 // TODO: Show progress.
246
247 CStringW strZipName;
248 INT appendMode;
250 {
251 strZipName = DoGetZipName(m_items[0]);
252 appendMode = APPEND_STATUS_CREATE;
253 }
254 else
255 {
256 strZipName = m_ExistingZip;
257 appendMode = APPEND_STATUS_ADDINZIP;
258 }
259
260 if (m_items.GetSize() <= 0)
261 {
262 DPRINT1("GetSize() <= 0\n");
263 return CZCERR_ZEROITEMS;
264 }
265
267 for (INT iItem = 0; iItem < m_items.GetSize(); ++iItem)
268 {
269 DoAddFilesFromItem(files, m_items[iItem]);
270 }
271
272 if (files.GetSize() <= 0)
273 {
274 DPRINT1("files.GetSize() <= 0\n");
275
277 CStringW strText;
278 strText.Format(IDS_NOFILES, static_cast<PCWSTR>(m_items[0]));
279 MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
280
281 return CZCERR_NOFILES;
282 }
283
285 ZeroMemory(&ffunc, sizeof(ffunc));
287
288 zipFile zf = zipOpen2_64(strZipName, appendMode, NULL, &ffunc);
289 if (zf == 0)
290 {
291 DPRINT1("zf == 0\n");
292
293 int err = CZCERR_CREATE;
294
296 CStringW strText;
297 strText.Format(IDS_CANTCREATEZIP, static_cast<PCWSTR>(strZipName), err);
298 MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
299
300 return err;
301 }
302
303 // TODO: password
304 const char *password = NULL;
305 int zip64 = 1; // always zip64
306 zip_fileinfo zi;
307
308 int err = 0;
309 CStringW strTarget, strBaseName = DoGetBaseName(m_items[0]);
310 UINT nCodePage = GetZipCodePage(FALSE);
311 for (INT iFile = 0; iFile < files.GetSize(); ++iFile)
312 {
313 const CStringW& strFile = files[iFile];
314
316 if (!DoReadAllOfFile(strFile, contents, &zi))
317 {
318 DPRINT1("DoReadAllOfFile failed\n");
320 strTarget = strFile;
321 break;
322 }
323
324 unsigned long crc = 0;
325 if (password)
326 {
327 // TODO: crc = ...;
328 }
329
330 CStringA strNameInZip = DoGetNameInZip(strBaseName, strFile, nCodePage);
331 CStringA strNameInZipUTF8 = DoGetNameInZip(strBaseName, strFile, CP_UTF8);
332 if (!m_TargetDir.IsEmpty())
333 {
334 CStringA strTargetDir = CStringA(CW2AEX<MAX_PATH>(m_TargetDir, nCodePage));
335 strNameInZip = strTargetDir + strNameInZip;
336
338 strNameInZipUTF8 = strTargetDirUTF8 + strNameInZipUTF8;
339 }
340
341 CSimpleArray<BYTE> extraField;
342 if (nCodePage != CP_UTF8 && strNameInZip != strNameInZipUTF8)
343 {
344 // Header
345 WORD headerID = EF_UNIPATH, dataSize = 1 + 4 + strNameInZipUTF8.GetLength();
346 extraField.Add(headerID & 0xFF);
347 extraField.Add((headerID >> 8) & 0xFF);
348 extraField.Add(dataSize & 0xFF);
349 extraField.Add((dataSize >> 8) & 0xFF);
350 extraField.Add(1); // Version
351
352 // CRC32
353 DWORD nameCRC = CalculateNameCRC32(strNameInZip);
354 extraField.Add(nameCRC & 0xFF);
355 extraField.Add((nameCRC >> 8) & 0xFF);
356 extraField.Add((nameCRC >> 16) & 0xFF);
357 extraField.Add((nameCRC >> 24) & 0xFF);
358
359 // UTF-8 name
360 for (INT ich = 0; ich < strNameInZipUTF8.GetLength(); ++ich)
361 extraField.Add(strNameInZipUTF8[ich]);
362 }
363
365 strNameInZip,
366 &zi,
367 (extraField.GetSize() > 0 ? extraField.GetData() : NULL),
368 extraField.GetSize(),
369 NULL,
370 0,
371 NULL,
374 0,
375 -MAX_WBITS,
378 password,
379 crc,
381 (nCodePage == CP_UTF8 ? MINIZIP_UTF8_FLAG : 0),
382 zip64);
383 if (err)
384 {
385 DPRINT1("zipOpenNewFileInZip3_64\n");
386 break;
387 }
388
389 err = zipWriteInFileInZip(zf, contents.GetData(), contents.GetSize());
390 if (err)
391 {
392 DPRINT1("zipWriteInFileInZip\n");
393 break;
394 }
395
397 if (err)
398 {
399 DPRINT1("zipCloseFileInZip\n");
400 break;
401 }
402 }
403
404 zipClose(zf, NULL);
405
406 if (err)
407 {
408 if (err && m_ExistingZip.IsEmpty())
409 DeleteFileW(strZipName);
410
412
413 CStringW strText;
414 if (err < 0)
415 strText.Format(IDS_CANTCREATEZIP, static_cast<PCWSTR>(strZipName), err);
416 else
417 strText.Format(IDS_CANTREADFILE, static_cast<PCWSTR>(strTarget));
418
419 MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
420 }
421 else
422 {
423 WCHAR szFullPath[MAX_PATH];
424 GetFullPathNameW(strZipName, _countof(szFullPath), szFullPath, NULL);
425
428 else
430 }
431
432 return err;
433}
LONG g_ModuleRefCnt
Definition: ACPPage.cpp:13
static CStringW DoGetZipName(PCWSTR filename)
Definition: CZipCreator.cpp:20
CZC_ERROR
@ CZCERR_NOFILES
@ CZCERR_ZEROITEMS
@ CZCERR_READ
@ CZCERR_CREATE
static unsigned __stdcall create_zip_function(void *arg)
static CStringA DoGetNameInZip(const CStringW &basename, const CStringW &filename, UINT nCodePage)
Definition: CZipCreator.cpp:52
static void DoAddFilesFromItem(CSimpleArray< CStringW > &files, PCWSTR item)
static CStringW DoGetBaseName(PCWSTR filename)
Definition: CZipCreator.cpp:42
static DWORD CalculateNameCRC32(PCSTR name)
Definition: CZipCreator.cpp:15
static BOOL DoReadAllOfFile(PCWSTR filename, CSimpleArray< BYTE > &contents, zip_fileinfo *pzi)
Definition: CZipCreator.cpp:70
#define EF_UNIPATH
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define DPRINT1
Definition: precomp.h:8
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
int GetSize() const
Definition: atlsimpcoll.h:104
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
bool IsEmpty() const noexcept
Definition: atlsimpstr.h:394
int GetLength() const noexcept
Definition: atlsimpstr.h:362
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:818
CStringT & MakeUpper()
Definition: cstringt.h:685
static BOOL runThread(CZipCreator *pCreator)
static CZipCreator * DoCreate(PCWSTR pszExistingZip=NULL, PCWSTR pszTargetDir=NULL)
struct CZipCreatorImpl * m_pimpl
Definition: CZipCreator.hpp:16
CComHeapPtr< ITEMIDLIST > m_pidlNotify
Definition: CZipCreator.hpp:17
virtual ~CZipCreator()
virtual void DoAddItem(PCWSTR pszFile)
static TAGID TAGID find
Definition: db.cpp:156
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define MINIZIP_COMPATIBLE_VERSION
Definition: precomp.h:41
UINT GetZipCodePage(BOOL bUnZip)
Definition: zipfldr.cpp:91
#define MINIZIP_UTF8_FLAG
Definition: precomp.h:43
#define IDS_CANTCREATEZIP
Definition: resource.h:50
#define IDS_ERRORTITLE
Definition: resource.h:47
#define IDS_CANTSTARTTHREAD
Definition: resource.h:48
#define IDS_CANTREADFILE
Definition: resource.h:51
#define IDS_NOFILES
Definition: resource.h:49
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
#define crc32(crc, buf, len)
Definition: inflate.c:1081
#define Z_DEFLATED
Definition: zlib.h:146
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:137
#define MAX_WBITS
Definition: zlib.h:151
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:130
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:880
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
void WINAPI PathRemoveExtensionW(WCHAR *path)
Definition: path.c:1946
BOOL WINAPI PathRemoveFileSpecW(WCHAR *path)
Definition: path.c:1145
BOOL WINAPI PathFileExistsW(const WCHAR *path)
Definition: path.c:2607
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
#define __stdcall
Definition: corecrt.h:120
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP uintptr_t __cdecl _beginthreadex(void *, unsigned int, _beginthreadex_start_routine_t, void *, unsigned int, unsigned int *)
Definition: thread.c:207
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1729
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DEF_MEM_LEVEL
Definition: zutil.h:53
GLenum GLsizei dataSize
Definition: glext.h:11123
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
static TfClientId tid
const char * filename
Definition: ioapi.h:137
void fill_win32_filefunc64W(zlib_filefunc64_def *pzlib_filefunc_def)
Definition: iowin32.c:457
#define ZeroMemory
Definition: minwinbase.h:31
#define FILE_FLAG_SEQUENTIAL_SCAN
Definition: disk.h:43
LPCWSTR szPath
Definition: env.c:37
static const char * contents
Definition: parser.c:511
static WCHAR password[]
Definition: url.c:33
_In_ HANDLE hFile
Definition: mswsock.h:90
CAtlStringA CStringA
Definition: atlstr.h:131
unsigned int UINT
Definition: ndis.h:50
HANDLE hThread
Definition: wizard.c:28
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define PathAddBackslashW
Definition: pathcch.h:302
#define PathAppendW
Definition: pathcch.h:310
#define err(...)
const WCHAR * str
#define CP_UTF8
Definition: nls.h:20
#define SHCNE_UPDATEITEM
Definition: shlobj.h:1910
#define SHCNE_UPDATEDIR
Definition: shlobj.h:1909
#define SHCNE_CREATE
Definition: shlobj.h:1898
#define SHCNF_PATHW
Definition: shlobj.h:1933
#define SHCNF_IDLIST
Definition: shlobj.h:1929
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
CStringW m_ExistingZip
unsigned JustDoIt()
CStringW m_TargetDir
CSimpleArray< CStringW > m_items
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
Definition: name.c:39
int tm_hour
Definition: zip.h:93
int tm_min
Definition: zip.h:92
int tm_sec
Definition: zip.h:91
int tm_mon
Definition: zip.h:95
int tm_year
Definition: zip.h:96
int tm_mday
Definition: zip.h:94
tm_zip tmz_date
Definition: zip.h:101
#define new(TYPE, numElems)
Definition: treelist.c:54
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
_In_ ULONG_PTR iFile
Definition: winddi.h:3835
void * arg
Definition: msvc.h:10
int WINAPI MessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
#define MB_ICONERROR
Definition: winuser.h:798
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193
int ZEXPORT zipClose(zipFile file, const char *global_comment)
Definition: zip.c:1883
int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char *password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64)
Definition: zip.c:1061
zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc *globalcomment, zlib_filefunc64_def *pzlib_filefunc_def)
Definition: zip.c:938
int ZEXPORT zipWriteInFileInZip(zipFile file, const void *buf, unsigned int len)
Definition: zip.c:1408
int ZEXPORT zipCloseFileInZip(zipFile file)
Definition: zip.c:1751
#define APPEND_STATUS_ADDINZIP
Definition: zip.h:114
#define APPEND_STATUS_CREATE
Definition: zip.h:112
voidp zipFile
Definition: zip.h:69