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 
  35 voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
  36 uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
  37 uLong   ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
  38 ZPOS64_T ZCALLBACK win32_tell64_file_func  OF((voidpf opaque, voidpf stream));
  39 long    ZCALLBACK win32_seek64_file_func  OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
  40 int     ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream));
  41 int     ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream));
  42 
  43 typedef struct
  44 {
  45     HANDLE hf;
  46     int error;
  47 } WIN32FILE_IOWIN;
  48 
  49 
  50 static 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 
  76 static 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 
  95 voidpf 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 
 124 voidpf 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 
 148 voidpf 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 
 168 voidpf 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 
 197 uLong 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 
 219 uLong 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 
 240 static 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 
 260 long 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 
 283 ZPOS64_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 
 308 long 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 
 346 long 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 
 385 int 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 
 403 int 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 
 413 void 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 
 425 void 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 
 438 void 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 
 451 void 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 }