added optional button to restart game (door, panel and touch variants)
[rocksndiamonds.git] / src / libgame / zip / iowin32.c
1 /* iowin32.c -- IO base function header for compress/uncompress .zip
2    Version 1.2.0, September 16th, 2017
3    part of the MiniZip project
4
5    Copyright (C) 2012-2017 Nathan Moinvaziri
6      https://github.com/nmoinvaz/minizip
7    Copyright (C) 2009-2010 Mathias Svensson
8      Modifications for Zip64 support
9      http://result42.com
10    Copyright (C) 1998-2010 Gilles Vollant
11      http://www.winimage.com/zLibDll/minizip.html
12
13    This program is distributed under the terms of the same license as zlib.
14    See the accompanying LICENSE file for the full text of the license.
15 */
16
17 #ifdef _WIN32
18
19 #include <stdlib.h>
20 #include <tchar.h>
21
22 #include "zlib.h"
23 #include "ioapi.h"
24 #include "iowin32.h"
25
26 #ifndef INVALID_HANDLE_VALUE
27 #  define INVALID_HANDLE_VALUE (0xFFFFFFFF)
28 #endif
29
30 #ifndef INVALID_SET_FILE_POINTER
31 #  define INVALID_SET_FILE_POINTER ((DWORD)-1)
32 #endif
33
34 #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API)))
35 #  if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
36 #    define IOWIN32_USING_WINRT_API 1
37 #  endif
38 #endif
39
40 uint32_t ZCALLBACK win32_read_file_func     (voidpf opaque, voidpf stream, void* buf, uint32_t size);
41 uint32_t ZCALLBACK win32_write_file_func    (voidpf opaque, voidpf stream, const void *buf, uint32_t size);
42 uint64_t ZCALLBACK win32_tell64_file_func   (voidpf opaque, voidpf stream);
43 long     ZCALLBACK win32_seek64_file_func   (voidpf opaque, voidpf stream, uint64_t offset, int origin);
44 int      ZCALLBACK win32_close_file_func    (voidpf opaque, voidpf stream);
45 int      ZCALLBACK win32_error_file_func    (voidpf opaque, voidpf stream);
46
47 typedef struct
48 {
49     HANDLE hf;
50     int error;
51     void *filename;
52     int filenameLength;
53 } WIN32FILE_IOWIN;
54
55
56 static void win32_translate_open_mode(int mode,
57                                       DWORD* lpdwDesiredAccess,
58                                       DWORD* lpdwCreationDisposition,
59                                       DWORD* lpdwShareMode,
60                                       DWORD* lpdwFlagsAndAttributes)
61 {
62     *lpdwDesiredAccess = 0;
63     *lpdwShareMode = 0;
64     *lpdwCreationDisposition = 0;
65     *lpdwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
66
67     if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
68     {
69         *lpdwDesiredAccess = GENERIC_READ;
70         *lpdwCreationDisposition = OPEN_EXISTING;
71         *lpdwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
72     }
73     else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
74     {
75         *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
76         *lpdwCreationDisposition = OPEN_EXISTING;
77     }
78     else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
79     {
80         *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
81         *lpdwCreationDisposition = CREATE_ALWAYS;
82     }
83 }
84
85 static voidpf win32_build_iowin(HANDLE hFile)
86 {
87     WIN32FILE_IOWIN *iowin = NULL;
88
89     if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
90     {
91         iowin = (WIN32FILE_IOWIN *)malloc(sizeof(WIN32FILE_IOWIN));
92         if (iowin == NULL)
93         {
94             CloseHandle(hFile);
95             return NULL;
96         }
97         memset(iowin, 0, sizeof(WIN32FILE_IOWIN));
98         iowin->hf = hFile;
99     }
100     return (voidpf)iowin;
101 }
102
103 static voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void *filename, int mode)
104 {
105     DWORD dwDesiredAccess, dwCreationDisposition, dwShareMode, dwFlagsAndAttributes ;
106     HANDLE hFile = NULL;
107     WIN32FILE_IOWIN *iowin = NULL;
108
109     win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode, &dwFlagsAndAttributes);
110
111     if ((filename != NULL) && (dwDesiredAccess != 0))
112     {
113 #ifdef IOWIN32_USING_WINRT_API
114         WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
115         MultiByteToWideChar(CP_ACP, 0, (const char*)filename, -1, filenameW, FILENAME_MAX + 0x200);
116         hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
117 #else
118         hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
119 #endif
120     }
121
122     iowin = win32_build_iowin(hFile);
123     if (iowin == NULL)
124         return NULL;
125     iowin->filenameLength = strlen(filename) + 1;
126     iowin->filename = (void*)malloc(iowin->filenameLength * sizeof(char));
127     strncpy(iowin->filename, filename, iowin->filenameLength);
128     return iowin;
129 }
130
131 static voidpf ZCALLBACK win32_opendisk64_file_funcA(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
132 {
133     WIN32FILE_IOWIN *iowin = NULL;
134     char *diskFilename = NULL;
135     voidpf ret = NULL;
136     int i = 0;
137
138     if (stream == NULL)
139         return NULL;
140     iowin = (WIN32FILE_IOWIN*)stream;
141     diskFilename = (char*)malloc(iowin->filenameLength * sizeof(char));
142     strncpy(diskFilename, iowin->filename, iowin->filenameLength);
143     for (i = iowin->filenameLength - 1; i >= 0; i -= 1)
144     {
145         if (diskFilename[i] != '.')
146             continue;
147         _snprintf(&diskFilename[i], iowin->filenameLength - i, ".z%02d", number_disk + 1);
148         break;
149     }
150     if (i >= 0)
151         ret = win32_open64_file_funcA(opaque, diskFilename, mode);
152     free(diskFilename);
153     return ret;
154 }
155
156 uint32_t ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size)
157 {
158     DWORD ret = 0;
159     HANDLE hFile = NULL;
160     if (stream != NULL)
161         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
162
163     if (hFile != NULL)
164     {
165         if (!ReadFile(hFile, buf, size, &ret, NULL))
166         {
167             DWORD dwErr = GetLastError();
168             if (dwErr == ERROR_HANDLE_EOF)
169                 dwErr = 0;
170             ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr;
171         }
172     }
173
174     return (uint32_t)ret;
175 }
176
177 uint32_t ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void *buf, uint32_t size)
178 {
179     DWORD ret = 0;
180     HANDLE hFile = NULL;
181     if (stream != NULL)
182         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
183
184     if (hFile != NULL)
185     {
186         if (!WriteFile(hFile, buf, size, &ret, NULL))
187         {
188             DWORD dwErr = GetLastError();
189             if (dwErr == ERROR_HANDLE_EOF)
190                 dwErr = 0;
191             ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr;
192         }
193     }
194
195     return (uint32_t)ret;
196 }
197
198 static BOOL win32_setfilepointer_internal(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod)
199 {
200 #ifdef IOWIN32_USING_WINRT_API
201     return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod);
202 #else
203     LONG lHigh = pos.HighPart;
204     BOOL ret = TRUE;
205     DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod);
206     if ((dwNewPos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
207         ret = FALSE;
208     if ((newPos != NULL) && (ret))
209     {
210         newPos->LowPart = dwNewPos;
211         newPos->HighPart = lHigh;
212     }
213     return ret;
214 #endif
215 }
216
217 uint64_t ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream)
218 {
219     uint64_t ret = (uint64_t)-1;
220     HANDLE hFile = NULL;
221     if (stream != NULL)
222         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
223
224     if (hFile)
225     {
226         LARGE_INTEGER pos;
227         pos.QuadPart = 0;
228         if (!win32_setfilepointer_internal(hFile, pos, &pos, FILE_CURRENT))
229         {
230             DWORD dwErr = GetLastError();
231             ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr;
232             ret = (uint64_t)-1;
233         }
234         else
235             ret = pos.QuadPart;
236     }
237     return ret;
238 }
239
240 long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, uint64_t offset, int origin)
241 {
242     DWORD dwMoveMethod = 0xFFFFFFFF;
243     HANDLE hFile = NULL;
244     long ret = -1;
245
246     if (stream != NULL)
247         hFile = ((WIN32FILE_IOWIN*)stream)->hf;
248
249     switch (origin)
250     {
251         case ZLIB_FILEFUNC_SEEK_CUR:
252             dwMoveMethod = FILE_CURRENT;
253             break;
254         case ZLIB_FILEFUNC_SEEK_END:
255             dwMoveMethod = FILE_END;
256             break;
257         case ZLIB_FILEFUNC_SEEK_SET:
258             dwMoveMethod = FILE_BEGIN;
259             break;
260         default:
261             return -1;
262     }
263
264     if (hFile)
265     {
266         LARGE_INTEGER pos;
267         pos.QuadPart = offset;
268         if (!win32_setfilepointer_internal(hFile, pos, NULL, dwMoveMethod))
269         {
270             DWORD dwErr = GetLastError();
271             ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr;
272             ret = -1;
273         }
274         else
275             ret = 0;
276     }
277     return ret;
278 }
279
280 int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream)
281 {
282     WIN32FILE_IOWIN* iowin = NULL;
283     int ret = -1;
284
285     if (stream == NULL)
286         return ret;
287     iowin = ((WIN32FILE_IOWIN*)stream);
288     if (iowin->filename != NULL)
289         free(iowin->filename);
290     if (iowin->hf != NULL)
291     {
292         CloseHandle(iowin->hf);
293         ret=0;
294     }
295     free(stream);
296     return ret;
297 }
298
299 int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream)
300 {
301     int ret = -1;
302     if (stream == NULL)
303         return ret;
304     ret = ((WIN32FILE_IOWIN*)stream)->error;
305     return ret;
306 }
307
308 void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def)
309 {
310     pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA;
311     pzlib_filefunc_def->zopendisk64_file = win32_opendisk64_file_funcA;
312     pzlib_filefunc_def->zread_file = win32_read_file_func;
313     pzlib_filefunc_def->zwrite_file = win32_write_file_func;
314     pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
315     pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
316     pzlib_filefunc_def->zclose_file = win32_close_file_func;
317     pzlib_filefunc_def->zerror_file = win32_error_file_func;
318     pzlib_filefunc_def->opaque = NULL;
319 }
320
321 #endif // _WIN32