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