X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Flibgame%2Fzip%2Fiowin32.c;fp=src%2Flibgame%2Fzip%2Fiowin32.c;h=53a96e650cc5c965d1a14482fd58ef6bcb50d85a;hb=fb81506227581bcc04cd4835b8e3f41a109d1f97;hp=0000000000000000000000000000000000000000;hpb=d1a163e883efe963cd1a83cf7a989add2bcb6740;p=rocksndiamonds.git diff --git a/src/libgame/zip/iowin32.c b/src/libgame/zip/iowin32.c new file mode 100644 index 00000000..53a96e65 --- /dev/null +++ b/src/libgame/zip/iowin32.c @@ -0,0 +1,591 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + Version 1.2.0, September 16th, 2017 + part of the MiniZip project + + Copyright (C) 2012-2017 Nathan Moinvaziri + https://github.com/nmoinvaz/minizip + Copyright (C) 2009-2010 Mathias Svensson + Modifications for Zip64 support + http://result42.com + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifdef _WIN32 + +#include +#include + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +# define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define IOWIN32_USING_WINRT_API 1 +# endif +#endif + +voidpf ZCALLBACK win32_open_file_func (voidpf opaque, const char *filename, int mode); +uint32_t ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf, uint32_t size); +uint32_t ZCALLBACK win32_write_file_func (voidpf opaque, voidpf stream, const void *buf, uint32_t size); +uint64_t ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream); +long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream, uint64_t offset, int origin); +int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream); +int ZCALLBACK win32_error_file_func (voidpf opaque, voidpf stream); + +typedef struct +{ + HANDLE hf; + int error; + void *filename; + int filenameLength; +} WIN32FILE_IOWIN; + + +static void win32_translate_open_mode(int mode, + DWORD* lpdwDesiredAccess, + DWORD* lpdwCreationDisposition, + DWORD* lpdwShareMode, + DWORD* lpdwFlagsAndAttributes) +{ + *lpdwDesiredAccess = 0; + *lpdwShareMode = 0; + *lpdwCreationDisposition = 0; + *lpdwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) + { + *lpdwDesiredAccess = GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + *lpdwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + } + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = CREATE_ALWAYS; + } +} + +static voidpf win32_build_iowin(HANDLE hFile) +{ + WIN32FILE_IOWIN *iowin = NULL; + + if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + iowin = (WIN32FILE_IOWIN *)malloc(sizeof(WIN32FILE_IOWIN)); + if (iowin == NULL) + { + CloseHandle(hFile); + return NULL; + } + memset(iowin, 0, sizeof(WIN32FILE_IOWIN)); + iowin->hf = hFile; + } + return (voidpf)iowin; +} + +static voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void *filename, int mode) +{ + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes; + HANDLE hFile = NULL; + WIN32FILE_IOWIN *iowin = NULL; + + win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode, &dwFlagsAndAttributes); + + if ((filename != NULL) && (dwDesiredAccess != 0)) + { +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP, 0, (const char*)filename, -1, filenameW, FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif +#else + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + } + + iowin = win32_build_iowin(hFile); + if (iowin == NULL) + return NULL; + iowin->filenameLength = _tcslen(filename) + 1; + iowin->filename = (void*)malloc(iowin->filenameLength * sizeof(TCHAR)); + _tcsncpy(iowin->filename, filename, iowin->filenameLength); + return iowin; +} + +static voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void *filename, int mode) +{ + DWORD dwDesiredAccess, dwCreationDisposition, dwShareMode, dwFlagsAndAttributes ; + HANDLE hFile = NULL; + WIN32FILE_IOWIN *iowin = NULL; + + win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode, &dwFlagsAndAttributes); + + if ((filename != NULL) && (dwDesiredAccess != 0)) + { +#ifdef IOWIN32_USING_WINRT_API + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP, 0, (const char*)filename, -1, filenameW, FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + } + + iowin = win32_build_iowin(hFile); + if (iowin == NULL) + return NULL; + iowin->filenameLength = strlen(filename) + 1; + iowin->filename = (void*)malloc(iowin->filenameLength * sizeof(char)); + strncpy(iowin->filename, filename, iowin->filenameLength); + return iowin; +} + +static voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void *filename, int mode) +{ + DWORD dwDesiredAccess, dwCreationDisposition, dwShareMode, dwFlagsAndAttributes; + HANDLE hFile = NULL; + WIN32FILE_IOWIN *iowin = NULL; + + win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode, &dwFlagsAndAttributes); + + if ((filename != NULL) && (dwDesiredAccess != 0)) + { +#ifdef IOWIN32_USING_WINRT_API + hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + } + + iowin = win32_build_iowin(hFile); + if (iowin == NULL) + return NULL; + if (iowin->filename == NULL) + { + iowin->filenameLength = wcslen(filename) + 1; + iowin->filename = (void*)malloc(iowin->filenameLength * sizeof(WCHAR)); + wcsncpy(iowin->filename, filename, iowin->filenameLength); + } + return iowin; +} + +voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char *filename, int mode) +{ + DWORD dwDesiredAccess, dwCreationDisposition, dwShareMode, dwFlagsAndAttributes ; + HANDLE hFile = NULL; + WIN32FILE_IOWIN *iowin = NULL; + + win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode, &dwFlagsAndAttributes); + + if ((filename != NULL) && (dwDesiredAccess != 0)) + { +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP, 0, (const char*)filename, -1, filenameW, FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif +#else + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + } + + iowin = win32_build_iowin(hFile); + if (iowin == NULL) + return NULL; + iowin->filenameLength = _tcslen((TCHAR*)filename) + 1; + iowin->filename = (void*)malloc(iowin->filenameLength * sizeof(TCHAR)); + _tcsncpy(iowin->filename, (TCHAR*)filename, iowin->filenameLength); + return iowin; +} + +static voidpf ZCALLBACK win32_opendisk64_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) +{ + WIN32FILE_IOWIN *iowin = NULL; + TCHAR *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + iowin = (WIN32FILE_IOWIN*)stream; + diskFilename = (TCHAR*)malloc(iowin->filenameLength * sizeof(TCHAR)); + _tcsncpy(diskFilename, iowin->filename, iowin->filenameLength); + for (i = iowin->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != _T('.')) + continue; + _sntprintf(&diskFilename[i], iowin->filenameLength - i, _T(".z%02d"), number_disk + 1); + break; + } + if (i >= 0) + ret = win32_open64_file_func(opaque, (char*)diskFilename, mode); + free(diskFilename); + return ret; +} + +static voidpf ZCALLBACK win32_opendisk64_file_funcW(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) +{ + WIN32FILE_IOWIN *iowin = NULL; + WCHAR *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + iowin = (WIN32FILE_IOWIN*)stream; + diskFilename = (WCHAR*)malloc((iowin->filenameLength + 10) * sizeof(WCHAR)); + wcsncpy(diskFilename, iowin->filename, iowin->filenameLength); + for (i = iowin->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != L'.') + continue; + _snwprintf(&diskFilename[i], (iowin->filenameLength + 10) - i, L".z%02d", number_disk + 1); + break; + } + if (i >= 0) + ret = win32_open64_file_funcW(opaque, diskFilename, mode); + free(diskFilename); + return ret; +} + +static voidpf ZCALLBACK win32_opendisk64_file_funcA(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) +{ + WIN32FILE_IOWIN *iowin = NULL; + char *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + iowin = (WIN32FILE_IOWIN*)stream; + diskFilename = (char*)malloc(iowin->filenameLength * sizeof(char)); + strncpy(diskFilename, iowin->filename, iowin->filenameLength); + for (i = iowin->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != '.') + continue; + _snprintf(&diskFilename[i], iowin->filenameLength - i, ".z%02d", number_disk + 1); + break; + } + if (i >= 0) + ret = win32_open64_file_funcA(opaque, diskFilename, mode); + free(diskFilename); + return ret; +} + +static voidpf ZCALLBACK win32_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) +{ + WIN32FILE_IOWIN *iowin = NULL; + TCHAR *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + iowin = (WIN32FILE_IOWIN*)stream; + diskFilename = (TCHAR*)malloc(iowin->filenameLength * sizeof(TCHAR)); + _tcsncpy(diskFilename, iowin->filename, iowin->filenameLength); + for (i = iowin->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != _T('.')) + continue; + _sntprintf(&diskFilename[i], iowin->filenameLength - i, _T(".z%02d"), number_disk + 1); + break; + } + if (i >= 0) + ret = win32_open_file_func(opaque, (char*)diskFilename, mode); + free(diskFilename); + return ret; +} + +uint32_t ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size) +{ + DWORD ret = 0; + HANDLE hFile = NULL; + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile != NULL) + { + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + } + } + + return (uint32_t)ret; +} + +uint32_t ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void *buf, uint32_t size) +{ + DWORD ret = 0; + HANDLE hFile = NULL; + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile != NULL) + { + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + } + } + + return (uint32_t)ret; +} + +static BOOL win32_setfilepointer_internal(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) +{ +#ifdef IOWIN32_USING_WINRT_API + return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); +#else + LONG lHigh = pos.HighPart; + BOOL ret = TRUE; + DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); + if ((dwNewPos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) + ret = FALSE; + if ((newPos != NULL) && (ret)) + { + newPos->LowPart = dwNewPos; + newPos->HighPart = lHigh; + } + return ret; +#endif +} + +static long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) +{ + long ret = -1; + HANDLE hFile = NULL; + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + if (!win32_setfilepointer_internal(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + ret = -1; + } + else + ret = (long)pos.LowPart; + } + return ret; +} + +uint64_t ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) +{ + uint64_t ret = (uint64_t)-1; + HANDLE hFile = NULL; + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + if (!win32_setfilepointer_internal(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + ret = (uint64_t)-1; + } + else + ret = pos.QuadPart; + } + return ret; +} + +static long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uint32_t offset, int origin) +{ + DWORD dwMoveMethod = 0xFFFFFFFF; + HANDLE hFile = NULL; + long ret = -1; + + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR: + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END: + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + dwMoveMethod = FILE_BEGIN; + break; + default: + return -1; + } + + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!win32_setfilepointer_internal(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + ret = -1; + } + else + ret = 0; + } + return ret; +} + +long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, uint64_t offset, int origin) +{ + DWORD dwMoveMethod = 0xFFFFFFFF; + HANDLE hFile = NULL; + long ret = -1; + + if (stream != NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR: + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END: + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + dwMoveMethod = FILE_BEGIN; + break; + default: + return -1; + } + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!win32_setfilepointer_internal(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream)->error = (int)dwErr; + ret = -1; + } + else + ret = 0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) +{ + WIN32FILE_IOWIN* iowin = NULL; + int ret = -1; + + if (stream == NULL) + return ret; + iowin = ((WIN32FILE_IOWIN*)stream); + if (iowin->filename != NULL) + free(iowin->filename); + if (iowin->hf != NULL) + { + CloseHandle(iowin->hf); + ret=0; + } + free(stream); + return ret; +} + +int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) +{ + int ret = -1; + if (stream == NULL) + return ret; + ret = ((WIN32FILE_IOWIN*)stream)->error; + return ret; +} + +void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zopendisk_file = win32_opendisk_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_func; + pzlib_filefunc_def->zopendisk64_file = win32_opendisk64_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; + pzlib_filefunc_def->zopendisk64_file = win32_opendisk64_file_funcA; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64W(zlib_filefunc64_def *pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; + pzlib_filefunc_def->zopendisk64_file = win32_opendisk64_file_funcW; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +#endif // _WIN32