1/* $Id: tif_win32.c,v 1.39 2011-12-22 17:07:57 bfriesen Exp $ */ 2 3/* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and 8 * its documentation for any purpose is hereby granted without fee, provided 9 * that (i) the above copyright notices and this permission notice appear in 10 * all copies of the software and related documentation, and (ii) the names of 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or 12 * publicity relating to the software without the specific, prior written 13 * permission of Sam Leffler and Silicon Graphics. 14 * 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27/* 28 * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by 29 * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA 30 */ 31#include "tiffiop.h" 32 33#include <windows.h> 34 35static tmsize_t 36_tiffReadProc(thandle_t fd, void* buf, tmsize_t size) 37{ 38 /* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes 39 * 32bit sizes, so we loop through the data in suitable 32bit sized 40 * chunks */ 41 uint8* ma; 42 uint64 mb; 43 DWORD n; 44 DWORD o; 45 tmsize_t p; 46 ma=(uint8*)buf; 47 mb=size; 48 p=0; 49 while (mb>0) 50 { 51 n=0x80000000UL; 52 if ((uint64)n>mb) 53 n=(DWORD)mb; 54 if (!ReadFile(fd,(LPVOID)ma,n,&o,NULL)) 55 return(0); 56 ma+=o; 57 mb-=o; 58 p+=o; 59 if (o!=n) 60 break; 61 } 62 return(p); 63} 64 65static tmsize_t 66_tiffWriteProc(thandle_t fd, void* buf, tmsize_t size) 67{ 68 /* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes 69 * 32bit sizes, so we loop through the data in suitable 32bit sized 70 * chunks */ 71 uint8* ma; 72 uint64 mb; 73 DWORD n; 74 DWORD o; 75 tmsize_t p; 76 ma=(uint8*)buf; 77 mb=size; 78 p=0; 79 while (mb>0) 80 { 81 n=0x80000000UL; 82 if ((uint64)n>mb) 83 n=(DWORD)mb; 84 if (!WriteFile(fd,(LPVOID)ma,n,&o,NULL)) 85 return(0); 86 ma+=o; 87 mb-=o; 88 p+=o; 89 if (o!=n) 90 break; 91 } 92 return(p); 93} 94 95static uint64 96_tiffSeekProc(thandle_t fd, uint64 off, int whence) 97{ 98 LARGE_INTEGER offli; 99 DWORD dwMoveMethod; 100 offli.QuadPart = off; 101 switch(whence) 102 { 103 case SEEK_SET: 104 dwMoveMethod = FILE_BEGIN; 105 break; 106 case SEEK_CUR: 107 dwMoveMethod = FILE_CURRENT; 108 break; 109 case SEEK_END: 110 dwMoveMethod = FILE_END; 111 break; 112 default: 113 dwMoveMethod = FILE_BEGIN; 114 break; 115 } 116 offli.LowPart=SetFilePointer(fd,offli.LowPart,&offli.HighPart,dwMoveMethod); 117 if ((offli.LowPart==INVALID_SET_FILE_POINTER)&&(GetLastError()!=NO_ERROR)) 118 offli.QuadPart=0; 119 return(offli.QuadPart); 120} 121 122static int 123_tiffCloseProc(thandle_t fd) 124{ 125 return (CloseHandle(fd) ? 0 : -1); 126} 127 128static uint64 129_tiffSizeProc(thandle_t fd) 130{ 131 ULARGE_INTEGER m; 132 m.LowPart=GetFileSize(fd,&m.HighPart); 133 return(m.QuadPart); 134} 135 136static int 137_tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize) 138{ 139 (void) fd; 140 (void) pbase; 141 (void) psize; 142 return (0); 143} 144 145/* 146 * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>: 147 * 148 * Windows uses both a handle and a pointer for file mapping, 149 * but according to the SDK documentation and Richter's book 150 * "Advanced Windows Programming" it is safe to free the handle 151 * after obtaining the file mapping pointer 152 * 153 * This removes a nasty OS dependency and cures a problem 154 * with Visual C++ 5.0 155 */ 156static int 157_tiffMapProc(thandle_t fd, void** pbase, toff_t* psize) 158{ 159 uint64 size; 160 tmsize_t sizem; 161 HANDLE hMapFile; 162 163 size = _tiffSizeProc(fd); 164 sizem = (tmsize_t)size; 165 if ((uint64)sizem!=size) 166 return (0); 167 168 /* By passing in 0 for the maximum file size, it specifies that we 169 create a file mapping object for the full file size. */ 170 hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL); 171 if (hMapFile == NULL) 172 return (0); 173 *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); 174 CloseHandle(hMapFile); 175 if (*pbase == NULL) 176 return (0); 177 *psize = size; 178 return(1); 179} 180 181static void 182_tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size) 183{ 184 (void) fd; 185 (void) base; 186 (void) size; 187} 188 189static void 190_tiffUnmapProc(thandle_t fd, void* base, toff_t size) 191{ 192 (void) fd; 193 (void) size; 194 UnmapViewOfFile(base); 195} 196 197/* 198 * Open a TIFF file descriptor for read/writing. 199 * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode 200 * string, which forces the file to be opened unmapped. 201 */ 202TIFF* 203TIFFFdOpen(int ifd, const char* name, const char* mode) 204{ 205 TIFF* tif; 206 int fSuppressMap; 207 int m; 208 fSuppressMap=0; 209 for (m=0; mode[m]!=0; m++) 210 { 211 if (mode[m]=='u') 212 { 213 fSuppressMap=1; 214 break; 215 } 216 } 217 tif = TIFFClientOpen(name, mode, (thandle_t)ifd, 218 _tiffReadProc, _tiffWriteProc, 219 _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, 220 fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, 221 fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc); 222 if (tif) 223 tif->tif_fd = ifd; 224 return (tif); 225} 226 227#ifndef _WIN32_WCE 228 229/* 230 * Open a TIFF file for read/writing. 231 */ 232TIFF* 233TIFFOpen(const char* name, const char* mode) 234{ 235 static const char module[] = "TIFFOpen"; 236 thandle_t fd; 237 int m; 238 DWORD dwMode; 239 TIFF* tif; 240 241 m = _TIFFgetMode(mode, module); 242 243 switch(m) { 244 case O_RDONLY: dwMode = OPEN_EXISTING; break; 245 case O_RDWR: dwMode = OPEN_ALWAYS; break; 246 case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; 247 case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; 248 case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; 249 default: return ((TIFF*)0); 250 } 251 252 fd = (thandle_t)CreateFileA(name, 253 (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE), 254 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, 255 (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, 256 NULL); 257 if (fd == INVALID_HANDLE_VALUE) { 258 TIFFErrorExt(0, module, "%s: Cannot open", name); 259 return ((TIFF *)0); 260 } 261 262 tif = TIFFFdOpen((int)fd, name, mode); 263 if(!tif) 264 CloseHandle(fd); 265 return tif; 266} 267 268/* 269 * Open a TIFF file with a Unicode filename, for read/writing. 270 */ 271TIFF* 272TIFFOpenW(const wchar_t* name, const char* mode) 273{ 274 static const char module[] = "TIFFOpenW"; 275 thandle_t fd; 276 int m; 277 DWORD dwMode; 278 int mbsize; 279 char *mbname; 280 TIFF *tif; 281 282 m = _TIFFgetMode(mode, module); 283 284 switch(m) { 285 case O_RDONLY: dwMode = OPEN_EXISTING; break; 286 case O_RDWR: dwMode = OPEN_ALWAYS; break; 287 case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; 288 case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; 289 case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; 290 default: return ((TIFF*)0); 291 } 292 293 fd = (thandle_t)CreateFileW(name, 294 (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), 295 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, 296 (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, 297 NULL); 298 if (fd == INVALID_HANDLE_VALUE) { 299 TIFFErrorExt(0, module, "%S: Cannot open", name); 300 return ((TIFF *)0); 301 } 302 303 mbname = NULL; 304 mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); 305 if (mbsize > 0) { 306 mbname = (char *)_TIFFmalloc(mbsize); 307 if (!mbname) { 308 TIFFErrorExt(0, module, 309 "Can't allocate space for filename conversion buffer"); 310 return ((TIFF*)0); 311 } 312 313 WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, 314 NULL, NULL); 315 } 316 317 tif = TIFFFdOpen((int)fd, 318 (mbname != NULL) ? mbname : "<unknown>", mode); 319 if(!tif) 320 CloseHandle(fd); 321 322 _TIFFfree(mbname); 323 324 return tif; 325} 326 327#endif /* ndef _WIN32_WCE */ 328 329void* 330_TIFFmalloc(tmsize_t s) 331{ 332 return (malloc((size_t) s)); 333} 334 335void 336_TIFFfree(void* p) 337{ 338 free(p); 339} 340 341void* 342_TIFFrealloc(void* p, tmsize_t s) 343{ 344 return (realloc(p, (size_t) s)); 345} 346 347void 348_TIFFmemset(void* p, int v, tmsize_t c) 349{ 350 memset(p, v, (size_t) c); 351} 352 353void 354_TIFFmemcpy(void* d, const void* s, tmsize_t c) 355{ 356 memcpy(d, s, (size_t) c); 357} 358 359int 360_TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) 361{ 362 return (memcmp(p1, p2, (size_t) c)); 363} 364 365#ifndef _WIN32_WCE 366 367#if (_MSC_VER < 1500) 368# define vsnprintf _vsnprintf 369#endif 370 371static void 372Win32WarningHandler(const char* module, const char* fmt, va_list ap) 373{ 374#ifndef TIF_PLATFORM_CONSOLE 375 LPTSTR szTitle; 376 LPTSTR szTmp; 377 LPCTSTR szTitleText = "%s Warning"; 378 LPCTSTR szDefaultModule = "LIBTIFF"; 379 LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; 380 SIZE_T nBufSize = (strlen(szTmpModule) + 381 strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); 382 383 if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) 384 return; 385 sprintf(szTitle, szTitleText, szTmpModule); 386 szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); 387 vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); 388 MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); 389 LocalFree(szTitle); 390 391 return; 392#else 393 if (module != NULL) 394 fprintf(stderr, "%s: ", module); 395 fprintf(stderr, "Warning, "); 396 vfprintf(stderr, fmt, ap); 397 fprintf(stderr, ".\n"); 398#endif 399} 400TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; 401 402static void 403Win32ErrorHandler(const char* module, const char* fmt, va_list ap) 404{ 405#ifndef TIF_PLATFORM_CONSOLE 406 LPTSTR szTitle; 407 LPTSTR szTmp; 408 LPCTSTR szTitleText = "%s Error"; 409 LPCTSTR szDefaultModule = "LIBTIFF"; 410 LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; 411 SIZE_T nBufSize = (strlen(szTmpModule) + 412 strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); 413 414 if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) 415 return; 416 sprintf(szTitle, szTitleText, szTmpModule); 417 szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); 418 vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); 419 MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); 420 LocalFree(szTitle); 421 return; 422#else 423 if (module != NULL) 424 fprintf(stderr, "%s: ", module); 425 vfprintf(stderr, fmt, ap); 426 fprintf(stderr, ".\n"); 427#endif 428} 429TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; 430 431#endif /* ndef _WIN32_WCE */ 432 433/* vim: set ts=8 sts=8 sw=8 noet: */ 434/* 435 * Local Variables: 436 * mode: c 437 * c-basic-offset: 8 438 * fill-column: 78 439 * End: 440 */ 441