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