2 * Copyright (c) 1988-1997 Sam Leffler
3 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by
27 * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
36 CreateFileA/CreateFileW return type 'HANDLE' while TIFFFdOpen() takes 'int',
37 which is formally incompatible and can even seemingly be of different size:
38 HANDLE is 64 bit under Win64, while int is still 32 bits there.
40 However, only the lower 32 bits of a HANDLE are significant under Win64 as,
41 for interoperability reasons, they must have the same values in 32- and
42 64-bit programs running on the same system, see
44 https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
46 Because of this, it is safe to define the following trivial functions for
47 casting between ints and HANDLEs, which are only really needed to avoid
48 compiler warnings (and, perhaps, to make the code slightly more clear).
49 Note that using the intermediate cast to "intptr_t" is crucial for warning
50 avoidance, as this integer type has the same size as HANDLE in all builds.
53 static inline thandle_t
thandle_from_int(int ifd
)
55 return (thandle_t
)(intptr_t)ifd
;
58 static inline int thandle_to_int(thandle_t fd
) { return (int)(intptr_t)fd
; }
60 static tmsize_t
_tiffReadProc(thandle_t fd
, void *buf
, tmsize_t size
)
62 /* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes
63 * 32bit sizes, so we loop through the data in suitable 32bit sized
78 if (!ReadFile(fd
, (LPVOID
)ma
, n
, &o
, NULL
))
89 static tmsize_t
_tiffWriteProc(thandle_t fd
, void *buf
, tmsize_t size
)
91 /* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes
92 * 32bit sizes, so we loop through the data in suitable 32bit sized
105 if ((uint64_t)n
> mb
)
107 if (!WriteFile(fd
, (LPVOID
)ma
, n
, &o
, NULL
))
118 static uint64_t _tiffSeekProc(thandle_t fd
, uint64_t off
, int whence
)
122 offli
.QuadPart
= off
;
126 dwMoveMethod
= FILE_BEGIN
;
129 dwMoveMethod
= FILE_CURRENT
;
132 dwMoveMethod
= FILE_END
;
135 dwMoveMethod
= FILE_BEGIN
;
139 SetFilePointer(fd
, offli
.LowPart
, &offli
.HighPart
, dwMoveMethod
);
140 if ((offli
.LowPart
== INVALID_SET_FILE_POINTER
) &&
141 (GetLastError() != NO_ERROR
))
143 return (offli
.QuadPart
);
146 static int _tiffCloseProc(thandle_t fd
) { return (CloseHandle(fd
) ? 0 : -1); }
148 static uint64_t _tiffSizeProc(thandle_t fd
)
151 if (GetFileSizeEx(fd
, &m
))
157 static int _tiffDummyMapProc(thandle_t fd
, void **pbase
, toff_t
*psize
)
166 * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>:
168 * Windows uses both a handle and a pointer for file mapping,
169 * but according to the SDK documentation and Richter's book
170 * "Advanced Windows Programming" it is safe to free the handle
171 * after obtaining the file mapping pointer
173 * This removes a nasty OS dependency and cures a problem
174 * with Visual C++ 5.0
176 static int _tiffMapProc(thandle_t fd
, void **pbase
, toff_t
*psize
)
182 size
= _tiffSizeProc(fd
);
183 sizem
= (tmsize_t
)size
;
184 if (!size
|| (uint64_t)sizem
!= size
)
187 /* By passing in 0 for the maximum file size, it specifies that we
188 create a file mapping object for the full file size. */
189 hMapFile
= CreateFileMapping(fd
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
190 if (hMapFile
== NULL
)
192 *pbase
= MapViewOfFile(hMapFile
, FILE_MAP_READ
, 0, 0, 0);
193 CloseHandle(hMapFile
);
200 static void _tiffDummyUnmapProc(thandle_t fd
, void *base
, toff_t size
)
207 static void _tiffUnmapProc(thandle_t fd
, void *base
, toff_t size
)
211 UnmapViewOfFile(base
);
215 * Open a TIFF file descriptor for read/writing.
216 * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
217 * string, which forces the file to be opened unmapped.
219 TIFF
*TIFFFdOpen(int ifd
, const char *name
, const char *mode
)
221 return TIFFFdOpenExt(ifd
, name
, mode
, NULL
);
224 TIFF
*TIFFFdOpenExt(int ifd
, const char *name
, const char *mode
,
225 TIFFOpenOptions
*opts
)
232 for (m
= 0; mode
[m
] != 0; m
++)
241 tif
= TIFFClientOpenExt(
242 name
, mode
, thandle_from_int(ifd
), _tiffReadProc
, _tiffWriteProc
,
243 _tiffSeekProc
, _tiffCloseProc
, _tiffSizeProc
,
244 fSuppressMap
? _tiffDummyMapProc
: _tiffMapProc
,
245 fSuppressMap
? _tiffDummyUnmapProc
: _tiffUnmapProc
, opts
);
254 * Open a TIFF file for read/writing.
256 TIFF
*TIFFOpen(const char *name
, const char *mode
)
258 return TIFFOpenExt(name
, mode
, NULL
);
261 TIFF
*TIFFOpenExt(const char *name
, const char *mode
, TIFFOpenOptions
*opts
)
263 static const char module
[] = "TIFFOpen";
269 m
= _TIFFgetMode(opts
, NULL
, mode
, module
);
274 dwMode
= OPEN_EXISTING
;
277 dwMode
= OPEN_EXISTING
;
279 case O_RDWR
| O_CREAT
:
280 dwMode
= OPEN_ALWAYS
;
282 case O_RDWR
| O_TRUNC
:
283 dwMode
= CREATE_ALWAYS
;
285 case O_RDWR
| O_CREAT
| O_TRUNC
:
286 dwMode
= CREATE_ALWAYS
;
292 fd
= (thandle_t
)CreateFileA(
293 name
, (m
== O_RDONLY
) ? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
294 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, dwMode
,
295 (m
== O_RDONLY
) ? FILE_ATTRIBUTE_READONLY
: FILE_ATTRIBUTE_NORMAL
,
297 if (fd
== INVALID_HANDLE_VALUE
)
299 _TIFFErrorEarly(opts
, NULL
, module
, "%s: Cannot open", name
);
303 tif
= TIFFFdOpenExt(thandle_to_int(fd
), name
, mode
, opts
);
310 * Open a TIFF file with a Unicode filename, for read/writing.
312 TIFF
*TIFFOpenW(const wchar_t *name
, const char *mode
)
314 return TIFFOpenWExt(name
, mode
, NULL
);
317 TIFF
*TIFFOpenWExt(const wchar_t *name
, const char *mode
, TIFFOpenOptions
*opts
)
319 static const char module
[] = "TIFFOpenW";
327 m
= _TIFFgetMode(opts
, NULL
, mode
, module
);
332 dwMode
= OPEN_EXISTING
;
335 dwMode
= OPEN_EXISTING
;
337 case O_RDWR
| O_CREAT
:
338 dwMode
= OPEN_ALWAYS
;
340 case O_RDWR
| O_TRUNC
:
341 dwMode
= CREATE_ALWAYS
;
343 case O_RDWR
| O_CREAT
| O_TRUNC
:
344 dwMode
= CREATE_ALWAYS
;
350 fd
= (thandle_t
)CreateFileW(
351 name
, (m
== O_RDONLY
) ? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
352 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, dwMode
,
353 (m
== O_RDONLY
) ? FILE_ATTRIBUTE_READONLY
: FILE_ATTRIBUTE_NORMAL
,
355 if (fd
== INVALID_HANDLE_VALUE
)
357 _TIFFErrorEarly(opts
, NULL
, module
, "%S: Cannot open", name
);
362 mbsize
= WideCharToMultiByte(CP_ACP
, 0, name
, -1, NULL
, 0, NULL
, NULL
);
365 mbname
= (char *)_TIFFmalloc(mbsize
);
370 "Can't allocate space for filename conversion buffer");
374 WideCharToMultiByte(CP_ACP
, 0, name
, -1, mbname
, mbsize
, NULL
, NULL
);
377 tif
= TIFFFdOpenExt(thandle_to_int(fd
),
378 (mbname
!= NULL
) ? mbname
: "<unknown>", mode
, opts
);
387 #endif /* ndef _WIN32_WCE */
389 void *_TIFFmalloc(tmsize_t s
)
392 return ((void *)NULL
);
394 return (malloc((size_t)s
));
397 void *_TIFFcalloc(tmsize_t nmemb
, tmsize_t siz
)
399 if (nmemb
== 0 || siz
== 0)
400 return ((void *)NULL
);
402 return calloc((size_t)nmemb
, (size_t)siz
);
405 void _TIFFfree(void *p
) { free(p
); }
407 void *_TIFFrealloc(void *p
, tmsize_t s
) { return (realloc(p
, (size_t)s
)); }
409 void _TIFFmemset(void *p
, int v
, tmsize_t c
) { memset(p
, v
, (size_t)c
); }
411 void _TIFFmemcpy(void *d
, const void *s
, tmsize_t c
)
413 memcpy(d
, s
, (size_t)c
);
416 int _TIFFmemcmp(const void *p1
, const void *p2
, tmsize_t c
)
418 return (memcmp(p1
, p2
, (size_t)c
));
423 static void Win32WarningHandler(const char *module
, const char *fmt
, va_list ap
)
426 fprintf(stderr
, "%s: ", module
);
427 fprintf(stderr
, "Warning, ");
428 vfprintf(stderr
, fmt
, ap
);
429 fprintf(stderr
, ".\n");
431 TIFFErrorHandler _TIFFwarningHandler
= Win32WarningHandler
;
433 static void Win32ErrorHandler(const char *module
, const char *fmt
, va_list ap
)
436 fprintf(stderr
, "%s: ", module
);
437 vfprintf(stderr
, fmt
, ap
);
438 fprintf(stderr
, ".\n");
440 TIFFErrorHandler _TIFFerrorHandler
= Win32ErrorHandler
;
442 #endif /* ndef _WIN32_WCE */