Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tiff/libtiff/tif_win32.c
4391 views
1
/*
2
* Copyright (c) 1988-1997 Sam Leffler
3
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
4
*
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.
12
*
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.
16
*
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
22
* OF THIS SOFTWARE.
23
*/
24
25
/*
26
* TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by
27
* Scott Wagner ([email protected]), Itek Graphix, Rochester, NY USA
28
*/
29
30
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
31
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
32
#endif
33
34
#include "tiffiop.h"
35
#include <stdlib.h>
36
37
#include <windows.h>
38
39
/*
40
CreateFileA/CreateFileW return type 'HANDLE' while TIFFFdOpen() takes 'int',
41
which is formally incompatible and can even seemingly be of different size:
42
HANDLE is 64 bit under Win64, while int is still 32 bits there.
43
44
However, only the lower 32 bits of a HANDLE are significant under Win64 as,
45
for interoperability reasons, they must have the same values in 32- and
46
64-bit programs running on the same system, see
47
48
https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
49
50
Because of this, it is safe to define the following trivial functions for
51
casting between ints and HANDLEs, which are only really needed to avoid
52
compiler warnings (and, perhaps, to make the code slightly more clear).
53
Note that using the intermediate cast to "intptr_t" is crucial for warning
54
avoidance, as this integer type has the same size as HANDLE in all builds.
55
*/
56
57
static inline thandle_t thandle_from_int(int ifd)
58
{
59
return (thandle_t)(intptr_t)ifd;
60
}
61
62
static inline int thandle_to_int(thandle_t fd) { return (int)(intptr_t)fd; }
63
64
static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size)
65
{
66
/* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes
67
* 32bit sizes, so we loop through the data in suitable 32bit sized
68
* chunks */
69
uint8_t *ma;
70
uint64_t mb;
71
DWORD n;
72
DWORD o;
73
tmsize_t p;
74
ma = (uint8_t *)buf;
75
mb = size;
76
p = 0;
77
while (mb > 0)
78
{
79
n = 0x80000000UL;
80
if ((uint64_t)n > mb)
81
n = (DWORD)mb;
82
if (!ReadFile(fd, (LPVOID)ma, n, &o, NULL))
83
return (0);
84
ma += o;
85
mb -= o;
86
p += o;
87
if (o != n)
88
break;
89
}
90
return (p);
91
}
92
93
static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size)
94
{
95
/* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes
96
* 32bit sizes, so we loop through the data in suitable 32bit sized
97
* chunks */
98
uint8_t *ma;
99
uint64_t mb;
100
DWORD n;
101
DWORD o;
102
tmsize_t p;
103
ma = (uint8_t *)buf;
104
mb = size;
105
p = 0;
106
while (mb > 0)
107
{
108
n = 0x80000000UL;
109
if ((uint64_t)n > mb)
110
n = (DWORD)mb;
111
if (!WriteFile(fd, (LPVOID)ma, n, &o, NULL))
112
return (0);
113
ma += o;
114
mb -= o;
115
p += o;
116
if (o != n)
117
break;
118
}
119
return (p);
120
}
121
122
static uint64_t _tiffSeekProc(thandle_t fd, uint64_t off, int whence)
123
{
124
LARGE_INTEGER offli;
125
DWORD dwMoveMethod;
126
offli.QuadPart = off;
127
switch (whence)
128
{
129
case SEEK_SET:
130
dwMoveMethod = FILE_BEGIN;
131
break;
132
case SEEK_CUR:
133
dwMoveMethod = FILE_CURRENT;
134
break;
135
case SEEK_END:
136
dwMoveMethod = FILE_END;
137
break;
138
default:
139
dwMoveMethod = FILE_BEGIN;
140
break;
141
}
142
offli.LowPart =
143
SetFilePointer(fd, offli.LowPart, &offli.HighPart, dwMoveMethod);
144
if ((offli.LowPart == INVALID_SET_FILE_POINTER) &&
145
(GetLastError() != NO_ERROR))
146
offli.QuadPart = 0;
147
return (offli.QuadPart);
148
}
149
150
static int _tiffCloseProc(thandle_t fd) { return (CloseHandle(fd) ? 0 : -1); }
151
152
static uint64_t _tiffSizeProc(thandle_t fd)
153
{
154
LARGE_INTEGER m;
155
if (GetFileSizeEx(fd, &m))
156
return (m.QuadPart);
157
else
158
return (0);
159
}
160
161
static int _tiffDummyMapProc(thandle_t fd, void **pbase, toff_t *psize)
162
{
163
(void)fd;
164
(void)pbase;
165
(void)psize;
166
return (0);
167
}
168
169
/*
170
* From "Hermann Josef Hill" <[email protected]>:
171
*
172
* Windows uses both a handle and a pointer for file mapping,
173
* but according to the SDK documentation and Richter's book
174
* "Advanced Windows Programming" it is safe to free the handle
175
* after obtaining the file mapping pointer
176
*
177
* This removes a nasty OS dependency and cures a problem
178
* with Visual C++ 5.0
179
*/
180
static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize)
181
{
182
uint64_t size;
183
tmsize_t sizem;
184
HANDLE hMapFile;
185
186
size = _tiffSizeProc(fd);
187
sizem = (tmsize_t)size;
188
if (!size || (uint64_t)sizem != size)
189
return (0);
190
191
/* By passing in 0 for the maximum file size, it specifies that we
192
create a file mapping object for the full file size. */
193
hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
194
if (hMapFile == NULL)
195
return (0);
196
*pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
197
CloseHandle(hMapFile);
198
if (*pbase == NULL)
199
return (0);
200
*psize = size;
201
return (1);
202
}
203
204
static void _tiffDummyUnmapProc(thandle_t fd, void *base, toff_t size)
205
{
206
(void)fd;
207
(void)base;
208
(void)size;
209
}
210
211
static void _tiffUnmapProc(thandle_t fd, void *base, toff_t size)
212
{
213
(void)fd;
214
(void)size;
215
UnmapViewOfFile(base);
216
}
217
218
/*
219
* Open a TIFF file descriptor for read/writing.
220
* Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
221
* string, which forces the file to be opened unmapped.
222
*/
223
TIFF *TIFFFdOpen(int ifd, const char *name, const char *mode)
224
{
225
return TIFFFdOpenExt(ifd, name, mode, NULL);
226
}
227
228
TIFF *TIFFFdOpenExt(int ifd, const char *name, const char *mode,
229
TIFFOpenOptions *opts)
230
{
231
TIFF *tif;
232
int fSuppressMap;
233
int m;
234
235
fSuppressMap = 0;
236
for (m = 0; mode[m] != 0; m++)
237
{
238
if (mode[m] == 'u')
239
{
240
fSuppressMap = 1;
241
break;
242
}
243
}
244
245
tif = TIFFClientOpenExt(
246
name, mode, thandle_from_int(ifd), _tiffReadProc, _tiffWriteProc,
247
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
248
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
249
fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc, opts);
250
if (tif)
251
tif->tif_fd = ifd;
252
return (tif);
253
}
254
255
#ifndef _WIN32_WCE
256
257
/*
258
* Open a TIFF file for read/writing.
259
*/
260
TIFF *TIFFOpen(const char *name, const char *mode)
261
{
262
return TIFFOpenExt(name, mode, NULL);
263
}
264
265
TIFF *TIFFOpenExt(const char *name, const char *mode, TIFFOpenOptions *opts)
266
{
267
static const char module[] = "TIFFOpen";
268
thandle_t fd;
269
int m;
270
DWORD dwMode;
271
TIFF *tif;
272
273
m = _TIFFgetMode(opts, NULL, mode, module);
274
275
switch (m)
276
{
277
case O_RDONLY:
278
dwMode = OPEN_EXISTING;
279
break;
280
case O_RDWR:
281
dwMode = OPEN_EXISTING;
282
break;
283
case O_RDWR | O_CREAT:
284
dwMode = OPEN_ALWAYS;
285
break;
286
case O_RDWR | O_TRUNC:
287
dwMode = CREATE_ALWAYS;
288
break;
289
case O_RDWR | O_CREAT | O_TRUNC:
290
dwMode = CREATE_ALWAYS;
291
break;
292
default:
293
return ((TIFF *)0);
294
}
295
296
fd = (thandle_t)CreateFileA(
297
name, (m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
298
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
299
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
300
NULL);
301
if (fd == INVALID_HANDLE_VALUE)
302
{
303
_TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name);
304
return ((TIFF *)0);
305
}
306
307
tif = TIFFFdOpenExt(thandle_to_int(fd), name, mode, opts);
308
if (!tif)
309
CloseHandle(fd);
310
return tif;
311
}
312
313
/*
314
* Open a TIFF file with a Unicode filename, for read/writing.
315
*/
316
TIFF *TIFFOpenW(const wchar_t *name, const char *mode)
317
{
318
return TIFFOpenWExt(name, mode, NULL);
319
}
320
321
TIFF *TIFFOpenWExt(const wchar_t *name, const char *mode, TIFFOpenOptions *opts)
322
{
323
static const char module[] = "TIFFOpenW";
324
thandle_t fd;
325
int m;
326
DWORD dwMode;
327
int mbsize;
328
char *mbname;
329
TIFF *tif;
330
331
m = _TIFFgetMode(opts, NULL, mode, module);
332
333
switch (m)
334
{
335
case O_RDONLY:
336
dwMode = OPEN_EXISTING;
337
break;
338
case O_RDWR:
339
dwMode = OPEN_EXISTING;
340
break;
341
case O_RDWR | O_CREAT:
342
dwMode = OPEN_ALWAYS;
343
break;
344
case O_RDWR | O_TRUNC:
345
dwMode = CREATE_ALWAYS;
346
break;
347
case O_RDWR | O_CREAT | O_TRUNC:
348
dwMode = CREATE_ALWAYS;
349
break;
350
default:
351
return ((TIFF *)0);
352
}
353
354
fd = (thandle_t)CreateFileW(
355
name, (m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
356
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
357
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
358
NULL);
359
if (fd == INVALID_HANDLE_VALUE)
360
{
361
_TIFFErrorEarly(opts, NULL, module, "%S: Cannot open", name);
362
return ((TIFF *)0);
363
}
364
365
mbname = NULL;
366
mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
367
if (mbsize > 0)
368
{
369
mbname = (char *)_TIFFmalloc(mbsize);
370
if (!mbname)
371
{
372
_TIFFErrorEarly(
373
opts, NULL, module,
374
"Can't allocate space for filename conversion buffer");
375
return ((TIFF *)0);
376
}
377
378
WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, NULL, NULL);
379
}
380
381
tif = TIFFFdOpenExt(thandle_to_int(fd),
382
(mbname != NULL) ? mbname : "<unknown>", mode, opts);
383
if (!tif)
384
CloseHandle(fd);
385
386
_TIFFfree(mbname);
387
388
return tif;
389
}
390
391
#endif /* ndef _WIN32_WCE */
392
393
void *_TIFFmalloc(tmsize_t s)
394
{
395
if (s == 0)
396
return ((void *)NULL);
397
398
return (malloc((size_t)s));
399
}
400
401
void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz)
402
{
403
if (nmemb == 0 || siz == 0)
404
return ((void *)NULL);
405
406
return calloc((size_t)nmemb, (size_t)siz);
407
}
408
409
void _TIFFfree(void *p) { free(p); }
410
411
void *_TIFFrealloc(void *p, tmsize_t s) { return (realloc(p, (size_t)s)); }
412
413
void _TIFFmemset(void *p, int v, tmsize_t c) { memset(p, v, (size_t)c); }
414
415
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
416
{
417
memcpy(d, s, (size_t)c);
418
}
419
420
int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c)
421
{
422
return (memcmp(p1, p2, (size_t)c));
423
}
424
425
#ifndef _WIN32_WCE
426
427
static void Win32WarningHandler(const char *module, const char *fmt, va_list ap)
428
{
429
if (module != NULL)
430
fprintf(stderr, "%s: ", module);
431
fprintf(stderr, "Warning, ");
432
vfprintf(stderr, fmt, ap);
433
fprintf(stderr, ".\n");
434
}
435
TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
436
437
static void Win32ErrorHandler(const char *module, const char *fmt, va_list ap)
438
{
439
if (module != NULL)
440
fprintf(stderr, "%s: ", module);
441
vfprintf(stderr, fmt, ap);
442
fprintf(stderr, ".\n");
443
}
444
TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
445
446
#endif /* ndef _WIN32_WCE */
447
448