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