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