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
8808 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
/*
162
* From "Hermann Josef Hill" <[email protected]>:
163
*
164
* Windows uses both a handle and a pointer for file mapping,
165
* but according to the SDK documentation and Richter's book
166
* "Advanced Windows Programming" it is safe to free the handle
167
* after obtaining the file mapping pointer
168
*
169
* This removes a nasty OS dependency and cures a problem
170
* with Visual C++ 5.0
171
*/
172
static int _tiffMapProc(thandle_t fd, void **pbase, toff_t *psize)
173
{
174
uint64_t size;
175
tmsize_t sizem;
176
HANDLE hMapFile;
177
178
size = _tiffSizeProc(fd);
179
sizem = (tmsize_t)size;
180
if (!size || (uint64_t)sizem != size)
181
return (0);
182
183
/* By passing in 0 for the maximum file size, it specifies that we
184
create a file mapping object for the full file size. */
185
hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
186
if (hMapFile == NULL)
187
return (0);
188
*pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
189
CloseHandle(hMapFile);
190
if (*pbase == NULL)
191
return (0);
192
*psize = size;
193
return (1);
194
}
195
196
static void _tiffUnmapProc(thandle_t fd, void *base, toff_t size)
197
{
198
(void)fd;
199
(void)size;
200
UnmapViewOfFile(base);
201
}
202
203
/*
204
* Open a TIFF file descriptor for read/writing.
205
* Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
206
* string, which forces the file to be opened unmapped.
207
*/
208
TIFF *TIFFFdOpen(int ifd, const char *name, const char *mode)
209
{
210
return TIFFFdOpenExt(ifd, name, mode, NULL);
211
}
212
213
TIFF *TIFFFdOpenExt(int ifd, const char *name, const char *mode,
214
TIFFOpenOptions *opts)
215
{
216
TIFF *tif;
217
int fSuppressMap;
218
int m;
219
220
fSuppressMap = 0;
221
for (m = 0; mode[m] != 0; m++)
222
{
223
if (mode[m] == 'u')
224
{
225
fSuppressMap = 1;
226
break;
227
}
228
}
229
230
tif = TIFFClientOpenExt(
231
name, mode, thandle_from_int(ifd), _tiffReadProc, _tiffWriteProc,
232
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
233
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
234
fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc, opts);
235
if (tif)
236
tif->tif_fd = ifd;
237
return (tif);
238
}
239
240
#ifndef _WIN32_WCE
241
242
/*
243
* Open a TIFF file for read/writing.
244
*/
245
TIFF *TIFFOpen(const char *name, const char *mode)
246
{
247
return TIFFOpenExt(name, mode, NULL);
248
}
249
250
TIFF *TIFFOpenExt(const char *name, const char *mode, TIFFOpenOptions *opts)
251
{
252
static const char module[] = "TIFFOpen";
253
thandle_t fd;
254
int m;
255
DWORD dwMode;
256
TIFF *tif;
257
258
m = _TIFFgetMode(opts, NULL, mode, module);
259
260
switch (m)
261
{
262
case O_RDONLY:
263
dwMode = OPEN_EXISTING;
264
break;
265
case O_RDWR:
266
dwMode = OPEN_EXISTING;
267
break;
268
case O_RDWR | O_CREAT:
269
dwMode = OPEN_ALWAYS;
270
break;
271
case O_RDWR | O_TRUNC:
272
dwMode = CREATE_ALWAYS;
273
break;
274
case O_RDWR | O_CREAT | O_TRUNC:
275
dwMode = CREATE_ALWAYS;
276
break;
277
default:
278
return ((TIFF *)0);
279
}
280
281
fd = (thandle_t)CreateFileA(
282
name, (m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
283
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
284
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
285
NULL);
286
if (fd == INVALID_HANDLE_VALUE)
287
{
288
_TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name);
289
return ((TIFF *)0);
290
}
291
292
tif = TIFFFdOpenExt(thandle_to_int(fd), name, mode, opts);
293
if (!tif)
294
CloseHandle(fd);
295
return tif;
296
}
297
298
/*
299
* Open a TIFF file with a Unicode filename, for read/writing.
300
*/
301
TIFF *TIFFOpenW(const wchar_t *name, const char *mode)
302
{
303
return TIFFOpenWExt(name, mode, NULL);
304
}
305
306
TIFF *TIFFOpenWExt(const wchar_t *name, const char *mode, TIFFOpenOptions *opts)
307
{
308
static const char module[] = "TIFFOpenW";
309
thandle_t fd;
310
int m;
311
DWORD dwMode;
312
int mbsize;
313
char *mbname;
314
TIFF *tif;
315
316
m = _TIFFgetMode(opts, NULL, mode, module);
317
318
switch (m)
319
{
320
case O_RDONLY:
321
dwMode = OPEN_EXISTING;
322
break;
323
case O_RDWR:
324
dwMode = OPEN_EXISTING;
325
break;
326
case O_RDWR | O_CREAT:
327
dwMode = OPEN_ALWAYS;
328
break;
329
case O_RDWR | O_TRUNC:
330
dwMode = CREATE_ALWAYS;
331
break;
332
case O_RDWR | O_CREAT | O_TRUNC:
333
dwMode = CREATE_ALWAYS;
334
break;
335
default:
336
return ((TIFF *)0);
337
}
338
339
fd = (thandle_t)CreateFileW(
340
name, (m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
341
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
342
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
343
NULL);
344
if (fd == INVALID_HANDLE_VALUE)
345
{
346
_TIFFErrorEarly(opts, NULL, module, "%S: Cannot open", name);
347
return ((TIFF *)0);
348
}
349
350
mbname = NULL;
351
mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
352
if (mbsize > 0)
353
{
354
mbname = (char *)_TIFFmalloc(mbsize);
355
if (!mbname)
356
{
357
_TIFFErrorEarly(
358
opts, NULL, module,
359
"Can't allocate space for filename conversion buffer");
360
return ((TIFF *)0);
361
}
362
363
WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, NULL, NULL);
364
}
365
366
tif = TIFFFdOpenExt(thandle_to_int(fd),
367
(mbname != NULL) ? mbname : "<unknown>", mode, opts);
368
if (!tif)
369
CloseHandle(fd);
370
371
_TIFFfree(mbname);
372
373
return tif;
374
}
375
376
#endif /* ndef _WIN32_WCE */
377
378
void *_TIFFmalloc(tmsize_t s)
379
{
380
if (s == 0)
381
return ((void *)NULL);
382
383
return (malloc((size_t)s));
384
}
385
386
void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz)
387
{
388
if (nmemb == 0 || siz == 0)
389
return ((void *)NULL);
390
391
return calloc((size_t)nmemb, (size_t)siz);
392
}
393
394
void _TIFFfree(void *p) { free(p); }
395
396
void *_TIFFrealloc(void *p, tmsize_t s) { return (realloc(p, (size_t)s)); }
397
398
void _TIFFmemset(void *p, int v, tmsize_t c) { memset(p, v, (size_t)c); }
399
400
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
401
{
402
memcpy(d, s, (size_t)c);
403
}
404
405
int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c)
406
{
407
return (memcmp(p1, p2, (size_t)c));
408
}
409
410
#ifndef _WIN32_WCE
411
412
static void Win32WarningHandler(const char *module, const char *fmt, va_list ap)
413
{
414
if (module != NULL)
415
fprintf(stderr, "%s: ", module);
416
fprintf(stderr, "Warning, ");
417
vfprintf(stderr, fmt, ap);
418
fprintf(stderr, ".\n");
419
}
420
TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
421
422
static void Win32ErrorHandler(const char *module, const char *fmt, va_list ap)
423
{
424
if (module != NULL)
425
fprintf(stderr, "%s: ", module);
426
vfprintf(stderr, fmt, ap);
427
fprintf(stderr, ".\n");
428
}
429
TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
430
431
#endif /* ndef _WIN32_WCE */
432
433