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
41voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
42uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
43uLong   ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
44ZPOS64_T ZCALLBACK win32_tell64_file_func  OF((voidpf opaque, voidpf stream));
45long    ZCALLBACK win32_seek64_file_func  OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
46int     ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream));
47int     ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream));
48
49typedef struct
50{
51    HANDLE hf;
52    int error;
53} WIN32FILE_IOWIN;
54
55
56static 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
82static 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
101voidpf 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
130voidpf 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
154voidpf 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
174voidpf 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
203uLong 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
225uLong 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
246static 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
266long 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
289ZPOS64_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
314long 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
352long 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
391int 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
409int 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
419void 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
431void 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
444void 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
457void 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