1 /* iowin32.c -- IO base function header for compress/uncompress .zip
2      Version 1.1, February 14h, 2010
3      part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4 
5          Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6 
7          Modifications for Zip64 support
8          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9 
10      For more info read MiniZip_info.txt
11 
12 */
13 
14 #include <stdlib.h>
15 
16 #include "zlib.h"
17 #include "ioapi.h"
18 #include "iowin32.h"
19 
20 #ifndef INVALID_HANDLE_VALUE
21 #define INVALID_HANDLE_VALUE (0xFFFFFFFF)
22 #endif
23 
24 #ifndef INVALID_SET_FILE_POINTER
25 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
26 #endif
27 
28 
29 // see Include/shared/winapifamily.h in the Windows Kit
30 #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API)))
31 
32 #if !defined(WINAPI_FAMILY_ONE_PARTITION)
33 #define WINAPI_FAMILY_ONE_PARTITION(PartitionSet, Partition) ((WINAPI_FAMILY & PartitionSet) == Partition)
34 #endif
35 
36 #if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP)
37 #define IOWIN32_USING_WINRT_API 1
38 #endif
39 #endif
40 
41 typedef struct
42 {
43     HANDLE hf;
44     int error;
45 } WIN32FILE_IOWIN;
46 
47 
win32_translate_open_mode(int mode,DWORD * lpdwDesiredAccess,DWORD * lpdwCreationDisposition,DWORD * lpdwShareMode,DWORD * lpdwFlagsAndAttributes)48 static void win32_translate_open_mode(int mode,
49                                       DWORD* lpdwDesiredAccess,
50                                       DWORD* lpdwCreationDisposition,
51                                       DWORD* lpdwShareMode,
52                                       DWORD* lpdwFlagsAndAttributes) {
53     *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0;
54 
55     if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
56     {
57         *lpdwDesiredAccess = GENERIC_READ;
58         *lpdwCreationDisposition = OPEN_EXISTING;
59         *lpdwShareMode = FILE_SHARE_READ;
60     }
61     else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
62     {
63         *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
64         *lpdwCreationDisposition = OPEN_EXISTING;
65     }
66     else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
67     {
68         *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
69         *lpdwCreationDisposition = CREATE_ALWAYS;
70     }
71 }
72 
win32_build_iowin(HANDLE hFile)73 static voidpf win32_build_iowin(HANDLE hFile) {
74     voidpf ret=NULL;
75 
76     if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
77     {
78         WIN32FILE_IOWIN w32fiow;
79         w32fiow.hf = hFile;
80         w32fiow.error = 0;
81         ret = malloc(sizeof(WIN32FILE_IOWIN));
82 
83         if (ret==NULL)
84             CloseHandle(hFile);
85         else
86             *((WIN32FILE_IOWIN*)ret) = w32fiow;
87     }
88     return ret;
89 }
90 
win32_open64_file_func(voidpf opaque,const void * filename,int mode)91 voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) {
92     const char* mode_fopen = NULL;
93     DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
94     HANDLE hFile = NULL;
95 
96     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
97 
98 #ifdef IOWIN32_USING_WINRT_API
99 #ifdef UNICODE
100     if ((filename!=NULL) && (dwDesiredAccess != 0))
101         hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
102 #else
103     if ((filename!=NULL) && (dwDesiredAccess != 0))
104     {
105         WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
106         MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
107         hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
108     }
109 #endif
110 #else
111     if ((filename!=NULL) && (dwDesiredAccess != 0))
112         hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
113 #endif
114 
115     return win32_build_iowin(hFile);
116 }
117 
118 
win32_open64_file_funcA(voidpf opaque,const void * filename,int mode)119 voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) {
120     const char* mode_fopen = NULL;
121     DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
122     HANDLE hFile = NULL;
123 
124     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
125 
126 #ifdef IOWIN32_USING_WINRT_API
127     if ((filename!=NULL) && (dwDesiredAccess != 0))
128     {
129         WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
130         MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
131         hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
132     }
133 #else
134     if ((filename!=NULL) && (dwDesiredAccess != 0))
135         hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
136 #endif
137 
138     return win32_build_iowin(hFile);
139 }
140 
141 
win32_open64_file_funcW(voidpf opaque,const void * filename,int mode)142 voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) {
143     const char* mode_fopen = NULL;
144     DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
145     HANDLE hFile = NULL;
146 
147     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
148 
149 #ifdef IOWIN32_USING_WINRT_API
150     if ((filename!=NULL) && (dwDesiredAccess != 0))
151         hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL);
152 #else
153     if ((filename!=NULL) && (dwDesiredAccess != 0))
154         hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
155 #endif
156 
157     return win32_build_iowin(hFile);
158 }
159 
160 
win32_open_file_func(voidpf opaque,const char * filename,int mode)161 voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) {
162     const char* mode_fopen = NULL;
163     DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
164     HANDLE hFile = NULL;
165 
166     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
167 
168 #ifdef IOWIN32_USING_WINRT_API
169 #ifdef UNICODE
170     if ((filename!=NULL) && (dwDesiredAccess != 0))
171         hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
172 #else
173     if ((filename!=NULL) && (dwDesiredAccess != 0))
174     {
175         WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
176         MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
177         hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
178     }
179 #endif
180 #else
181     if ((filename!=NULL) && (dwDesiredAccess != 0))
182         hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
183 #endif
184 
185     return win32_build_iowin(hFile);
186 }
187 
188 
win32_read_file_func(voidpf opaque,voidpf stream,void * buf,uLong size)189 uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) {
190     uLong ret=0;
191     HANDLE hFile = NULL;
192     if (stream!=NULL)
193         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
194 
195     if (hFile != NULL)
196     {
197         if (!ReadFile(hFile, buf, size, &ret, NULL))
198         {
199             DWORD dwErr = GetLastError();
200             if (dwErr == ERROR_HANDLE_EOF)
201                 dwErr = 0;
202             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
203         }
204     }
205 
206     return ret;
207 }
208 
209 
win32_write_file_func(voidpf opaque,voidpf stream,const void * buf,uLong size)210 uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) {
211     uLong ret=0;
212     HANDLE hFile = NULL;
213     if (stream!=NULL)
214         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
215 
216     if (hFile != NULL)
217     {
218         if (!WriteFile(hFile, buf, size, &ret, NULL))
219         {
220             DWORD dwErr = GetLastError();
221             if (dwErr == ERROR_HANDLE_EOF)
222                 dwErr = 0;
223             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
224         }
225     }
226 
227     return ret;
228 }
229 
MySetFilePointerEx(HANDLE hFile,LARGE_INTEGER pos,LARGE_INTEGER * newPos,DWORD dwMoveMethod)230 static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) {
231 #ifdef IOWIN32_USING_WINRT_API
232     return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod);
233 #else
234     LONG lHigh = pos.HighPart;
235     DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod);
236     BOOL fOk = TRUE;
237     if (dwNewPos == 0xFFFFFFFF)
238         if (GetLastError() != NO_ERROR)
239             fOk = FALSE;
240     if ((newPos != NULL) && (fOk))
241     {
242         newPos->LowPart = dwNewPos;
243         newPos->HighPart = lHigh;
244     }
245     return fOk;
246 #endif
247 }
248 
win32_tell_file_func(voidpf opaque,voidpf stream)249 long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) {
250     long ret=-1;
251     HANDLE hFile = NULL;
252     if (stream!=NULL)
253         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
254     if (hFile != NULL)
255     {
256         LARGE_INTEGER pos;
257         pos.QuadPart = 0;
258 
259         if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
260         {
261             DWORD dwErr = GetLastError();
262             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
263             ret = -1;
264         }
265         else
266             ret=(long)pos.LowPart;
267     }
268     return ret;
269 }
270 
win32_tell64_file_func(voidpf opaque,voidpf stream)271 ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) {
272     ZPOS64_T ret= (ZPOS64_T)-1;
273     HANDLE hFile = NULL;
274     if (stream!=NULL)
275         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
276 
277     if (hFile)
278     {
279         LARGE_INTEGER pos;
280         pos.QuadPart = 0;
281 
282         if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
283         {
284             DWORD dwErr = GetLastError();
285             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
286             ret = (ZPOS64_T)-1;
287         }
288         else
289             ret=pos.QuadPart;
290     }
291     return ret;
292 }
293 
294 
win32_seek_file_func(voidpf opaque,voidpf stream,uLong offset,int origin)295 long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) {
296     DWORD dwMoveMethod=0xFFFFFFFF;
297     HANDLE hFile = NULL;
298 
299     long ret=-1;
300     if (stream!=NULL)
301         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
302     switch (origin)
303     {
304     case ZLIB_FILEFUNC_SEEK_CUR :
305         dwMoveMethod = FILE_CURRENT;
306         break;
307     case ZLIB_FILEFUNC_SEEK_END :
308         dwMoveMethod = FILE_END;
309         break;
310     case ZLIB_FILEFUNC_SEEK_SET :
311         dwMoveMethod = FILE_BEGIN;
312         break;
313     default: return -1;
314     }
315 
316     if (hFile != NULL)
317     {
318         LARGE_INTEGER pos;
319         pos.QuadPart = offset;
320         if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod))
321         {
322             DWORD dwErr = GetLastError();
323             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
324             ret = -1;
325         }
326         else
327             ret=0;
328     }
329     return ret;
330 }
331 
win32_seek64_file_func(voidpf opaque,voidpf stream,ZPOS64_T offset,int origin)332 long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
333     DWORD dwMoveMethod=0xFFFFFFFF;
334     HANDLE hFile = NULL;
335     long ret=-1;
336 
337     if (stream!=NULL)
338         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
339 
340     switch (origin)
341     {
342         case ZLIB_FILEFUNC_SEEK_CUR :
343             dwMoveMethod = FILE_CURRENT;
344             break;
345         case ZLIB_FILEFUNC_SEEK_END :
346             dwMoveMethod = FILE_END;
347             break;
348         case ZLIB_FILEFUNC_SEEK_SET :
349             dwMoveMethod = FILE_BEGIN;
350             break;
351         default: return -1;
352     }
353 
354     if (hFile)
355     {
356         LARGE_INTEGER pos;
357         pos.QuadPart = offset;
358         if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod))
359         {
360             DWORD dwErr = GetLastError();
361             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
362             ret = -1;
363         }
364         else
365             ret=0;
366     }
367     return ret;
368 }
369 
win32_close_file_func(voidpf opaque,voidpf stream)370 int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) {
371     int ret=-1;
372 
373     if (stream!=NULL)
374     {
375         HANDLE hFile;
376         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
377         if (hFile != NULL)
378         {
379             CloseHandle(hFile);
380             ret=0;
381         }
382         free(stream);
383     }
384     return ret;
385 }
386 
win32_error_file_func(voidpf opaque,voidpf stream)387 int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) {
388     int ret=-1;
389     if (stream!=NULL)
390     {
391         ret = ((WIN32FILE_IOWIN*)stream) -> error;
392     }
393     return ret;
394 }
395 
fill_win32_filefunc(zlib_filefunc_def * pzlib_filefunc_def)396 void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def) {
397     pzlib_filefunc_def->zopen_file = win32_open_file_func;
398     pzlib_filefunc_def->zread_file = win32_read_file_func;
399     pzlib_filefunc_def->zwrite_file = win32_write_file_func;
400     pzlib_filefunc_def->ztell_file = win32_tell_file_func;
401     pzlib_filefunc_def->zseek_file = win32_seek_file_func;
402     pzlib_filefunc_def->zclose_file = win32_close_file_func;
403     pzlib_filefunc_def->zerror_file = win32_error_file_func;
404     pzlib_filefunc_def->opaque = NULL;
405 }
406 
fill_win32_filefunc64(zlib_filefunc64_def * pzlib_filefunc_def)407 void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) {
408     pzlib_filefunc_def->zopen64_file = win32_open64_file_func;
409     pzlib_filefunc_def->zread_file = win32_read_file_func;
410     pzlib_filefunc_def->zwrite_file = win32_write_file_func;
411     pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
412     pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
413     pzlib_filefunc_def->zclose_file = win32_close_file_func;
414     pzlib_filefunc_def->zerror_file = win32_error_file_func;
415     pzlib_filefunc_def->opaque = NULL;
416 }
417 
418 
fill_win32_filefunc64A(zlib_filefunc64_def * pzlib_filefunc_def)419 void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) {
420     pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA;
421     pzlib_filefunc_def->zread_file = win32_read_file_func;
422     pzlib_filefunc_def->zwrite_file = win32_write_file_func;
423     pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
424     pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
425     pzlib_filefunc_def->zclose_file = win32_close_file_func;
426     pzlib_filefunc_def->zerror_file = win32_error_file_func;
427     pzlib_filefunc_def->opaque = NULL;
428 }
429 
430 
fill_win32_filefunc64W(zlib_filefunc64_def * pzlib_filefunc_def)431 void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) {
432     pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW;
433     pzlib_filefunc_def->zread_file = win32_read_file_func;
434     pzlib_filefunc_def->zwrite_file = win32_write_file_func;
435     pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
436     pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
437     pzlib_filefunc_def->zclose_file = win32_close_file_func;
438     pzlib_filefunc_def->zerror_file = win32_error_file_func;
439     pzlib_filefunc_def->opaque = NULL;
440 }
441