ReactOS  0.4.14-dev-1256-g2125fec
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 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 {
20 
22  ret += L".zip";
23 
24  UINT i = 2;
25  while (PathFileExistsW(ret))
26  {
27  CStringW str;
28  str.Format(L" (%u).zip", i++);
29 
30  ret = szPath;
31  ret += str;
32  }
33 
34  return ret;
35 }
36 
38 {
39  CHAR buf[MAX_PATH];
41  return buf;
42 }
43 
45 {
46  WCHAR szBaseName[MAX_PATH];
47  StringCbCopyW(szBaseName, sizeof(szBaseName), filename);
48  PathRemoveFileSpecW(szBaseName);
49  PathAddBackslashW(szBaseName);
50  return szBaseName;
51 }
52 
53 static CStringA
55 {
56  CStringW basenameI = basename, filenameI = filename;
57  basenameI.MakeUpper();
58  filenameI.MakeUpper();
59 
60  CStringW ret;
61  if (filenameI.Find(basenameI) == 0)
62  ret = filename.Mid(basename.GetLength());
63  else
64  ret = filename;
65 
66  ret.Replace(L'\\', L'/');
67 
68  return DoGetAnsiName(ret);
69 }
70 
71 static BOOL
73  zip_fileinfo *pzi)
74 {
75  contents.RemoveAll();
76 
81  {
82  DPRINT1("%S: cannot open\n", filename);
83  return FALSE;
84  }
85 
86  FILETIME ft, ftLocal;
87  ZeroMemory(pzi, sizeof(*pzi));
88  if (GetFileTime(hFile, NULL, NULL, &ft))
89  {
90  SYSTEMTIME st;
91  FileTimeToLocalFileTime(&ft, &ftLocal);
92  FileTimeToSystemTime(&ftLocal, &st);
93  pzi->tmz_date.tm_sec = st.wSecond;
94  pzi->tmz_date.tm_min = st.wMinute;
95  pzi->tmz_date.tm_hour = st.wHour;
96  pzi->tmz_date.tm_mday = st.wDay;
97  pzi->tmz_date.tm_mon = st.wMonth - 1;
98  pzi->tmz_date.tm_year = st.wYear;
99  }
100 
101  const DWORD cbBuff = 0x7FFF;
102  LPBYTE pbBuff = reinterpret_cast<LPBYTE>(CoTaskMemAlloc(cbBuff));
103  if (!pbBuff)
104  {
105  DPRINT1("Out of memory\n");
107  return FALSE;
108  }
109 
110  for (;;)
111  {
112  DWORD cbRead;
113  if (!ReadFile(hFile, pbBuff, cbBuff, &cbRead, NULL) || !cbRead)
114  break;
115 
116  for (DWORD i = 0; i < cbRead; ++i)
117  contents.Add(pbBuff[i]);
118  }
119 
120  CoTaskMemFree(pbBuff);
122 
123  return TRUE;
124 }
125 
126 static void
128 {
129  if (!PathIsDirectoryW(item))
130  {
131  files.Add(item);
132  return;
133  }
134 
136  StringCbCopyW(szPath, sizeof(szPath), item);
137  PathAppendW(szPath, L"*");
138 
140  HANDLE hFind = FindFirstFileW(szPath, &find);
141  if (hFind == INVALID_HANDLE_VALUE)
142  return;
143 
144  do
145  {
146  if (wcscmp(find.cFileName, L".") == 0 ||
147  wcscmp(find.cFileName, L"..") == 0)
148  {
149  continue;
150  }
151 
152  StringCbCopyW(szPath, sizeof(szPath), item);
153  PathAppendW(szPath, find.cFileName);
154 
155  if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
156  DoAddFilesFromItem(files, szPath);
157  else
158  files.Add(szPath);
159  } while (FindNextFileW(hFind, &find));
160 
161  FindClose(hFind);
162 }
163 
165 {
167 
168  unsigned JustDoIt();
169 };
170 
172 {
174 }
175 
177 {
179  delete m_pimpl;
180 }
181 
182 static unsigned __stdcall
184 {
185  CZipCreator *pCreator = reinterpret_cast<CZipCreator *>(arg);
186  return pCreator->m_pimpl->JustDoIt();
187 }
188 
190 {
191  unsigned tid = 0;
192  HANDLE hThread = reinterpret_cast<HANDLE>(
193  _beginthreadex(NULL, 0, create_zip_function, pCreator, 0, &tid));
194 
195  if (hThread)
196  {
198  return TRUE;
199  }
200 
201  DPRINT1("hThread == NULL\n");
202 
205  MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
206 
207  delete pCreator;
208  return FALSE;
209 }
210 
212 {
213  // canonicalize path
216 
217  m_pimpl->m_items.Add(szPath);
218 }
219 
221 {
226 };
227 
229 {
230  // TODO: Show progress.
231 
232  if (m_items.GetSize() <= 0)
233  {
234  DPRINT1("GetSize() <= 0\n");
235  return CZCERR_ZEROITEMS;
236  }
237 
239  for (INT iItem = 0; iItem < m_items.GetSize(); ++iItem)
240  {
241  DoAddFilesFromItem(files, m_items[iItem]);
242  }
243 
244  if (files.GetSize() <= 0)
245  {
246  DPRINT1("files.GetSize() <= 0\n");
247 
249  CStringW strText;
250  strText.Format(IDS_NOFILES, static_cast<LPCWSTR>(m_items[0]));
251  MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
252 
253  return CZCERR_NOFILES;
254  }
255 
256  zlib_filefunc64_def ffunc;
257  fill_win32_filefunc64W(&ffunc);
258 
259  CStringW strZipName = DoGetZipName(m_items[0]);
260  zipFile zf = zipOpen2_64(strZipName, APPEND_STATUS_CREATE, NULL, &ffunc);
261  if (zf == 0)
262  {
263  DPRINT1("zf == 0\n");
264 
265  int err = CZCERR_CREATE;
266 
268  CStringW strText;
269  strText.Format(IDS_CANTCREATEZIP, static_cast<LPCWSTR>(strZipName), err);
270  MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
271 
272  return err;
273  }
274 
275  // TODO: password
276  const char *password = NULL;
277  int zip64 = 1; // always zip64
278  zip_fileinfo zi;
279 
280  int err = 0;
281  CStringW strTarget, strBaseName = DoGetBaseName(m_items[0]);
282  for (INT iFile = 0; iFile < files.GetSize(); ++iFile)
283  {
284  const CStringW& strFile = files[iFile];
285 
286  CSimpleArray<BYTE> contents;
287  if (!DoReadAllOfFile(strFile, contents, &zi))
288  {
289  DPRINT1("DoReadAllOfFile failed\n");
290  err = CZCERR_READ;
291  strTarget = strFile;
292  break;
293  }
294 
295  unsigned long crc = 0;
296  if (password)
297  {
298  // TODO: crc = ...;
299  }
300 
301  CStringA strNameInZip = DoGetNameInZip(strBaseName, strFile);
303  strNameInZip,
304  &zi,
305  NULL,
306  0,
307  NULL,
308  0,
309  NULL,
310  Z_DEFLATED,
312  0,
313  -MAX_WBITS,
316  password,
317  crc,
318  zip64);
319  if (err)
320  {
321  DPRINT1("zipOpenNewFileInZip3_64\n");
322  break;
323  }
324 
325  err = zipWriteInFileInZip(zf, contents.GetData(), contents.GetSize());
326  if (err)
327  {
328  DPRINT1("zipWriteInFileInZip\n");
329  break;
330  }
331 
332  err = zipCloseFileInZip(zf);
333  if (err)
334  {
335  DPRINT1("zipCloseFileInZip\n");
336  break;
337  }
338  }
339 
340  zipClose(zf, NULL);
341 
342  if (err)
343  {
344  DeleteFileW(strZipName);
345 
347 
348  CStringW strText;
349  if (err < 0)
350  strText.Format(IDS_CANTCREATEZIP, static_cast<LPCWSTR>(strZipName), err);
351  else
352  strText.Format(IDS_CANTREADFILE, static_cast<LPCWSTR>(strTarget));
353 
354  MessageBoxW(NULL, strText, strTitle, MB_ICONERROR);
355  }
356 
357  return err;
358 }
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1702
static CStringW DoGetBaseName(LPCWSTR filename)
Definition: CZipCreator.cpp:44
struct CZipCreatorImpl * m_pimpl
Definition: CZipCreator.hpp:16
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:624
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
#define WideCharToMultiByte
Definition: compat.h:101
#define new(TYPE, numElems)
Definition: treelist.c:54
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
WORD wMonth
Definition: winbase.h:884
virtual ~CZipCreator()
unsigned JustDoIt()
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
LONG g_ModuleRefCnt
Definition: ACPPage.cpp:13
#define CP_ACP
Definition: compat.h:99
char CHAR
Definition: xmlstorage.h:175
void fill_win32_filefunc64W(zlib_filefunc64_def *pzlib_filefunc_def)
Definition: iowin32.c:452
uInt tm_mday
Definition: zip.h:94
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
#define ZeroMemory
Definition: winbase.h:1648
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:688
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
static CStringA DoGetAnsiName(LPCWSTR filename)
Definition: CZipCreator.cpp:37
const char * filename
Definition: ioapi.h:135
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
#define IDS_ERRORTITLE
Definition: resource.h:39
int GetSize() const
Definition: atlsimpcoll.h:104
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
int32_t INT
Definition: typedefs.h:57
#define FILE_SHARE_READ
Definition: compat.h:125
#define IDS_NOFILES
Definition: resource.h:41
virtual void DoAddItem(LPCWSTR pszFile)
BOOL WINAPI PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend)
Definition: path.c:121
CStringT & MakeUpper()
Definition: cstringt.h:572
#define IDS_CANTREADFILE
Definition: resource.h:43
WORD wYear
Definition: winbase.h:883
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
unsigned char * LPBYTE
Definition: typedefs.h:53
void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
Definition: path.c:818
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:289
unsigned int BOOL
Definition: ntddk_ex.h:94
static CStringW DoGetZipName(LPCWSTR filename)
Definition: CZipCreator.cpp:15
int ZEXPORT zipWriteInFileInZip(zipFile file, const void *buf, unsigned int len)
Definition: zip.c:1409
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
CZC_ERROR
static BOOL DoReadAllOfFile(LPCWSTR filename, CSimpleArray< BYTE > &contents, zip_fileinfo *pzi)
Definition: CZipCreator.cpp:72
const WCHAR * str
WORD wMinute
Definition: winbase.h:888
smooth NULL
Definition: ftsmooth.c:416
#define IDS_CANTSTARTTHREAD
Definition: resource.h:40
voidp zipFile
Definition: zip.h:69
#define Z_DEFLATED
Definition: zlib.h:209
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1756
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:193
#define OPEN_EXISTING
Definition: compat.h:434
static BOOL runThread(CZipCreator *pCreator)
static unsigned __stdcall create_zip_function(void *arg)
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define _countof(array)
Definition: sndvol32.h:68
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
#define __stdcall
Definition: typedefs.h:25
uInt tm_mon
Definition: zip.h:95
WORD wSecond
Definition: winbase.h:889
int ret
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedDecrement
Definition: armddk.h:52
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
#define MB_ICONERROR
Definition: winuser.h:781
#define IDS_CANTCREATEZIP
Definition: resource.h:42
#define GENERIC_READ
Definition: compat.h:124
uInt tm_year
Definition: zip.h:96
#define err(...)
_In_ HANDLE hFile
Definition: mswsock.h:90
int ZEXPORT zipOpenNewFileInZip3_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, int zip64)
Definition: zip.c:1303
WORD wDay
Definition: winbase.h:886
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define InterlockedIncrement
Definition: armddk.h:53
static ATOM item
Definition: dde.c:856
uInt tm_sec
Definition: zip.h:91
#define FILE_FLAG_SEQUENTIAL_SCAN
Definition: disk.h:43
LPCWSTR szPath
Definition: env.c:35
WORD wHour
Definition: winbase.h:887
unsigned int UINT
Definition: ndis.h:50
zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc *globalcomment, zlib_filefunc64_def *pzlib_filefunc_def)
Definition: zip.c:939
HANDLE hThread
Definition: wizard.c:27
#define DPRINT1
Definition: precomp.h:8
#define CreateFileW
Definition: compat.h:408
int ZEXPORT zipCloseFileInZip(zipFile file)
Definition: zip.c:1757
static TAGID TAGID find
Definition: db.cpp:153
tm_zip tmz_date
Definition: zip.h:101
_In_ ULONG_PTR iFile
Definition: winddi.h:3835
CSimpleArray< CStringW > m_items
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define DEF_MEM_LEVEL
Definition: zutil.h:53
uInt tm_hour
Definition: zip.h:93
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
#define MAX_WBITS
Definition: zconf.h:270
#define APPEND_STATUS_CREATE
Definition: zip.h:112
static TfClientId tid
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1046
static CStringA DoGetNameInZip(const CStringW &basename, const CStringW &filename)
Definition: CZipCreator.cpp:54
int ZEXPORT zipClose(zipFile file, const char *global_comment)
Definition: zip.c:1889
uInt tm_min
Definition: zip.h:92
static void DoAddFilesFromItem(CSimpleArray< CStringW > &files, LPCWSTR item)
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502